Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Event.cs @ 17053

Last change on this file since 17053 was 17053, checked in by abeham, 5 years ago

#2975: merged to stable

File size: 8.8 KB
Line 
1#region License Information
2/* SimSharp - A .NET port of SimPy, discrete event simulation framework
3Copyright (C) 2019  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 Simulation 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(Simulation 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    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
94    public virtual void Trigger(Event @event, int priority = 0) {
95      if (IsTriggered)
96        throw new InvalidOperationException("Event has already been triggered.");
97      IsOk = @event.IsOk;
98      Value = @event.Value;
99      IsTriggered = true;
100      Environment.Schedule(this, priority);
101    }
102
103    /// <summary>
104    /// This method schedules the event right now. It sets IsOk state to true
105    /// and optionally uses also the value. If urgent is given, the event may
106    /// be scheduled as urgent. Urgent events are placed in a separate event
107    /// queue. The callbacks of urgent events are executed before normal events.
108    /// </summary>
109    /// <exception cref="InvalidOperationException">
110    /// Thrown when the event has already been triggered.
111    /// </exception>
112    /// <param name="value">The value that the event should use.</param>
113    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
114    public virtual void Succeed(object value = null, int priority = 0) {
115      if (IsTriggered)
116        throw new InvalidOperationException("Event has already been triggered.");
117      IsOk = true;
118      Value = value;
119      IsTriggered = true;
120      Environment.Schedule(this, priority);
121    }
122
123    /// <summary>
124    /// This method schedules the event right now. It sets IsOk state to false
125    /// and optionally uses also the value. If urgent is given, the event may
126    /// be scheduled as urgent. Urgent events are placed in a separate event
127    /// queue. The callbacks of urgent events are executed before normal events.
128    /// </summary>
129    /// <exception cref="InvalidOperationException">
130    /// Thrown when the event has already been triggered.
131    /// </exception>
132    /// <param name="value">The value that the event should use.</param>
133    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
134    public virtual void Fail(object value = null, int priority = 0) {
135      if (IsTriggered)
136        throw new InvalidOperationException("Event has already been triggered.");
137      IsOk = false;
138      Value = value;
139      IsTriggered = true;
140      Environment.Schedule(this, priority);
141    }
142
143    /// <summary>
144    /// This method adds a callback to the list of callbacks. Callbacks will be
145    /// executed in the order they have been added.
146    /// </summary>
147    /// <param name="callback">The callback to execute when the event is being
148    /// processed.</param>
149    public virtual void AddCallback(Action<Event> callback) {
150      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
151      CallbackList.Add(callback);
152    }
153
154    /// <summary>
155    /// This method adds a range of callbacks to the list of callbacks. Callbacks
156    /// will be executed in the order they have been added.
157    /// </summary>
158    /// <param name="callbacks">The callbacks to execute when the event is being
159    /// processed.</param>
160    public virtual void AddCallbacks(IEnumerable<Action<Event>> callbacks) {
161      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
162      CallbackList.AddRange(callbacks);
163    }
164
165    /// <summary>
166    /// This method removes a callback to the list of callbacks.
167    /// </summary>
168    /// <remarks>
169    /// It is not checked if the callback has actually been added before and
170    /// no exception will be thrown if it had not been present.
171    /// </remarks>
172    /// <param name="callback">The callback to remove.</param>
173    public virtual void RemoveCallback(Action<Event> callback) {
174      if (IsProcessed) throw new InvalidOperationException("Event is already processed.");
175      CallbackList.Remove(callback);
176    }
177
178    /// <summary>
179    /// This method processes the event, that is, it calls all the callbacks.
180    /// When it finishes it will be marked IsProcessed and cannot be processed
181    /// again.
182    /// </summary>
183    /// <exception cref="InvalidOperationException">When the event has already
184    /// been processed.</exception>
185    public virtual void Process() {
186      if (IsProcessed) throw new InvalidOperationException("Event has already been processed.");
187      IsProcessed = true;
188      for (var i = 0; i < CallbackList.Count; i++)
189        CallbackList[i](this);
190      CallbackList = null;
191    }
192
193    public static Condition operator &(Event event1, Event event2) {
194      return new AllOf(event1.Environment, event1, event2);
195    }
196    public static Condition operator |(Event event1, Event event2) {
197      return new AnyOf(event1.Environment, event1, event2);
198    }
199  }
200}
Note: See TracBrowser for help on using the repository browser.