Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.2/SimSharp-3.3.2/Core/Events/Event.cs @ 18023

Last change on this file since 18023 was 18023, checked in by jkarder, 3 years ago

#3065: update Sim# to 3.3.2

File size: 8.0 KB
Line 
1#region License Information
2/*
3 * This file is part of SimSharp which is licensed under the MIT license.
4 * See the LICENSE file in the project root for more information.
5 */
6#endregion
7
8using System;
9using System.Collections.Generic;
10
11namespace SimSharp {
12  /// <summary>
13  /// The base class for all events in SimSharp.
14  /// An event can be in one of three states at any time:
15  ///  - Alive: The event object exists, but is neither scheduled to
16  ///           be executed, nor is it already executed.
17  ///  - Triggered: The event has been put in the event queue and is
18  ///               going to be executed.
19  ///  - Processed: The event has been executed.
20  ///
21  /// Usually, the event is alive until its Trigger, Succeed, or Fail
22  /// method have been called. Then it becomes triggered. When the
23  /// Environment progresses to the event and executes its callbacks
24  /// the event becomes processed.
25  /// </summary>
26  public class Event {
27    protected internal Simulation Environment { get; private set; }
28    protected List<Action<Event>> CallbackList { get; set; }
29
30    /// <summary>
31    /// The value property can be used to return arbitrary data from a
32    /// process or an event. It also represents the interrupt cause to
33    /// a process.
34    /// </summary>
35    public object Value { get; protected set; }
36
37    /// <summary>
38    /// The IsOk flag indicates if the event succeeded or failed. An event
39    /// that failed indicates to a waiting process that the action could
40    /// not be performed and that the faulting situation must be handled.
41    /// Typically, interrupting a process sets the IsOk flag to false.
42    /// </summary>
43    public bool IsOk { get; protected set; }
44    /// <summary>
45    /// An event is alive when it is not triggered and not processed. That
46    /// is, when it exists in memory without being scheduled. Typically,
47    /// a Process is alive until its last event has been processed and the
48    /// process event itself is to be processed.
49    /// </summary>
50    public bool IsAlive { get { return !IsTriggered && !IsProcessed; } }
51    /// <summary>
52    /// An event becomes processed when its callbacks have been executed.
53    /// Events may only be processed once and an exception will be thrown
54    /// if they are to be processed multiple times.
55    /// </summary>
56    public bool IsProcessed { get; protected set; }
57    /// <summary>
58    /// An event becomes triggered when it is placed into the event queue.
59    /// That is, when its callbacks are going to be executed.
60    /// An even that is triggered may later not be failed or retriggered.
61    /// </summary>
62    public bool IsTriggered { get; protected set; }
63
64    public Event(Simulation environment) {
65      Environment = environment;
66      CallbackList = new List<Action<Event>>();
67    }
68
69    /// <summary>
70    /// This method schedules the event right now. It takes the IsOk state
71    /// and uses the <see cref="Value"/> of the given <paramref name="@event"/>.
72    /// Thus if the given event fails, this event will also be triggered as
73    /// failing.
74    /// </summary>
75    /// <exception cref="InvalidOperationException">
76    /// Thrown when the event has already been triggered.
77    /// </exception>
78    /// <remarks>
79    /// The signature of this method allows it to be used as a callback.
80    /// </remarks>
81    /// <param name="event">The event that triggers this event.</param>
82    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
83    public virtual void Trigger(Event @event, int priority = 0) {
84      if (IsTriggered)
85        throw new InvalidOperationException("Event has already been triggered.");
86      IsOk = @event.IsOk;
87      Value = @event.Value;
88      IsTriggered = true;
89      Environment.Schedule(this, priority);
90    }
91
92    /// <summary>
93    /// This method schedules the event right now. It sets IsOk state to true
94    /// and optionally uses also the value. If urgent is given, the event may
95    /// be scheduled as urgent. Urgent events are placed in a separate event
96    /// queue. The callbacks of urgent events are executed before normal events.
97    /// </summary>
98    /// <exception cref="InvalidOperationException">
99    /// Thrown when the event has already been triggered.
100    /// </exception>
101    /// <param name="value">The value that the event should use.</param>
102    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
103    public virtual void Succeed(object value = null, int priority = 0) {
104      if (IsTriggered)
105        throw new InvalidOperationException("Event has already been triggered.");
106      IsOk = true;
107      Value = value;
108      IsTriggered = true;
109      Environment.Schedule(this, priority);
110    }
111
112    /// <summary>
113    /// This method schedules the event right now. It sets IsOk state to false
114    /// and optionally uses also the value. If urgent is given, the event may
115    /// be scheduled as urgent. Urgent events are placed in a separate event
116    /// queue. The callbacks of urgent events are executed before normal events.
117    /// </summary>
118    /// <exception cref="InvalidOperationException">
119    /// Thrown when the event has already been triggered.
120    /// </exception>
121    /// <param name="value">The value that the event should use.</param>
122    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
123    public virtual void Fail(object value = null, int priority = 0) {
124      if (IsTriggered)
125        throw new InvalidOperationException("Event has already been triggered.");
126      IsOk = false;
127      Value = value;
128      IsTriggered = true;
129      Environment.Schedule(this, priority);
130    }
131
132    /// <summary>
133    /// This method adds a callback to the list of callbacks. Callbacks will be
134    /// executed in the order they have been added.
135    /// </summary>
136    /// <param name="callback">The callback to execute when the event is being
137    /// processed.</param>
138    public virtual void AddCallback(Action<Event> callback) {
139      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
140      CallbackList.Add(callback);
141    }
142
143    /// <summary>
144    /// This method adds a range of callbacks to the list of callbacks. Callbacks
145    /// will be executed in the order they have been added.
146    /// </summary>
147    /// <param name="callbacks">The callbacks to execute when the event is being
148    /// processed.</param>
149    public virtual void AddCallbacks(IEnumerable<Action<Event>> callbacks) {
150      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
151      CallbackList.AddRange(callbacks);
152    }
153
154    /// <summary>
155    /// This method removes a callback to the list of callbacks.
156    /// </summary>
157    /// <remarks>
158    /// It is not checked if the callback has actually been added before and
159    /// no exception will be thrown if it had not been present.
160    /// </remarks>
161    /// <param name="callback">The callback to remove.</param>
162    public virtual void RemoveCallback(Action<Event> callback) {
163      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
164      CallbackList.Remove(callback);
165    }
166
167    /// <summary>
168    /// This method processes the event, that is, it calls all the callbacks.
169    /// When it finishes it will be marked IsProcessed and cannot be processed
170    /// again.
171    /// </summary>
172    /// <exception cref="InvalidOperationException">When the event has already
173    /// been processed.</exception>
174    public virtual void Process() {
175      if (IsProcessed) throw new InvalidOperationException("Event has already been processed.");
176      IsProcessed = true;
177      for (var i = 0; i < CallbackList.Count; i++)
178        CallbackList[i](this);
179      CallbackList = null;
180    }
181
182    public static Condition operator &(Event event1, Event event2) {
183      return new AllOf(event1.Environment, event1, event2);
184    }
185    public static Condition operator |(Event event1, Event event2) {
186      return new AnyOf(event1.Environment, event1, event2);
187    }
188  }
189}
Note: See TracBrowser for help on using the repository browser.