Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.0.7/SimSharp-3.0.7/Core/Events/Event.cs @ 14185

Last change on this file since 14185 was 14185, checked in by swagner, 8 years ago

#2526: Updated year of copyrights in license headers

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