Refactored IEventListener and IEventSink to handle garbage data according to configur...
[lwes-dotnet/github-mirror.git] / Org.Lwes / Status.cs
blob07f4b14cd25a664622de6ebfe1c937981c7bb281
1 namespace Org.Lwes
3 using System;
4 using System.Threading;
6 /// <summary>
7 /// Utility structure for performing and tracking threadsafe state transitions.
8 /// </summary>
9 /// <typeparam name="E">State type E (should be an enum)</typeparam>
10 public struct Status<E>
12 #region Fields
14 int _status;
16 #endregion Fields
18 #region Constructors
20 /// <summary>
21 /// Creates a new instance.
22 /// </summary>
23 /// <param name="initialialState">Initial state</param>
24 public Status(E initialialState)
26 _status = Convert.ToInt32(initialialState);
29 #endregion Constructors
31 #region Properties
33 /// <summary>
34 /// Accesses the current state.
35 /// </summary>
36 public E CurrentState
38 get { return (E)Enum.ToObject(typeof(E), Thread.VolatileRead(ref _status)); }
41 #endregion Properties
43 #region Methods
45 /// <summary>
46 /// Determines if the current state is greater than the comparand.
47 /// </summary>
48 /// <param name="comparand">comparand</param>
49 /// <returns><em>true</em> if the current state is greater than <paramref name="comparand"/>; otherwise <em>false</em></returns>
50 public bool IsGreaterThan(E comparand)
52 return Thread.VolatileRead(ref _status) > Convert.ToInt32(comparand);
55 /// <summary>
56 /// Determines if the current state is less than the comparand.
57 /// </summary>
58 /// <param name="comparand">comparand</param>
59 /// <returns><em>true</em> if the current state is less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
60 public bool IsLessThan(E comparand)
62 return Thread.VolatileRead(ref _status) < Convert.ToInt32(comparand);
65 /// <summary>
66 /// Transitions to the given state.
67 /// </summary>
68 /// <param name="value">the target state</param>
69 public void SetState(E value)
71 Thread.VolatileWrite(ref _status, Convert.ToInt32(value));
74 /// <summary>
75 /// Performs a state transition if the current state compares greater than the <paramref name="comparand"/>
76 /// </summary>
77 /// <param name="value">the target state</param>
78 /// <param name="comparand">comparand state</param>
79 /// <returns><em>true</em> if the current state compares greater than <paramref name="comparand"/>; otherwise <em>false</em></returns>
80 public bool SetStateIfGreaterThan(E value, E comparand)
82 int c = Convert.ToInt32(comparand);
83 int v = Convert.ToInt32(value);
85 int init, fin = Thread.VolatileRead(ref _status);
86 while (true)
88 if (fin < c) return false;
90 init = fin;
91 fin = Interlocked.CompareExchange(ref _status, v, init);
92 if (fin == init) return true;
96 /// <summary>
97 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
98 /// </summary>
99 /// <param name="value">the target state</param>
100 /// <param name="comparand">comparand state</param>
101 /// <returns><em>true</em> if the current state compares less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
102 public bool SetStateIfLessThan(E value, E comparand)
104 int c = Convert.ToInt32(comparand);
105 int v = Convert.ToInt32(value);
107 int init, fin = Thread.VolatileRead(ref _status);
108 while (true)
110 if (fin > c) return false;
112 init = fin;
113 fin = Interlocked.CompareExchange(ref _status, v, init);
114 if (fin == init) return true;
118 /// <summary>
119 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
120 /// </summary>
121 /// <param name="value">the target state</param>
122 /// <param name="comparand">comparand state</param>
123 /// <param name="actionOnSuccess">An action to be performed if the state transition succeeds</param>
124 /// <returns><em>true</em> if the current state compares less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
125 public bool SetStateIfLessThan(E value, E comparand, Action actionOnSuccess)
127 if (actionOnSuccess == null) throw new ArgumentNullException("actionOnSuccess");
128 if (SetStateIfLessThan(value, comparand))
130 actionOnSuccess();
131 return true;
133 return false;
136 /// <summary>
137 /// Toggles between the toggle state and the desired state - with
138 /// a spin-wait if necessary.
139 /// </summary>
140 /// <param name="desired">desired state</param>
141 /// <param name="toggle">state from which the desired state can toggle</param>
142 /// <returns><em>true</em> if the state transitions to the desired state from the toggle state; otherwise <em>false</em></returns>
143 public bool SpinToggleState(E desired, E toggle)
145 int d = Convert.ToInt32(desired);
146 int t = Convert.ToInt32(toggle);
148 spin:
149 int r = Interlocked.CompareExchange(ref _status, d, t);
150 // If the state was the toggle state then we're successful and done...
151 if (r == t) return true;
152 // otherwise if the result is anything but the desired state we're
153 // unsuccessful and done...
154 if (r != d) return false;
155 // otherwise we spin
156 goto spin;
159 /// <summary>
160 /// Perfroms a spinwait until the current state equals the target state.
161 /// </summary>
162 /// <param name="targetState">the target state</param>
163 /// <param name="loopAction">An action to perform inside the spin cycle</param>
164 public void SpinWaitForState(E targetState, Action loopAction)
166 int state = Convert.ToInt32(targetState);
167 while (Thread.VolatileRead(ref _status) != state)
169 loopAction();
173 /// <summary>
174 /// Tries to transition the state
175 /// </summary>
176 /// <param name="value">the target state</param>
177 /// <param name="comparand">comparand state must match current state</param>
178 /// <returns><em>true</em> if the current state matches <paramref name="comparand"/> and the state is transitioned to <paramref name="value"/>; otherwise <em>false</em></returns>
179 public bool TryTransition(E value, E comparand)
181 int c = Convert.ToInt32(comparand);
182 return Interlocked.CompareExchange(ref _status, Convert.ToInt32(value), c) == c;
185 /// <summary>
186 /// Tries to transition the state. Upon success executes the action given.
187 /// </summary>
188 /// <param name="value">the target state</param>
189 /// <param name="comparand">comparand state must match current state</param>
190 /// <param name="actionOnSuccess">action to perform if the state transition is successful</param>
191 /// <returns><em>true</em> if the current state matches <paramref name="comparand"/> and the state is transitioned to <paramref name="value"/>; otherwise <em>false</em></returns>
192 public bool TryTransition(E value, E comparand, Action actionOnSuccess)
194 if (actionOnSuccess == null) throw new ArgumentNullException("actionOnSuccess");
195 if (TryTransition(value, comparand))
197 actionOnSuccess();
198 return true;
200 return false;
203 #endregion Methods
205 internal E CompareExchange(E value, E comparand)
207 return
208 (E)Enum.ToObject(typeof(E), Interlocked.CompareExchange(ref _status, Convert.ToInt32(value), Convert.ToInt32(comparand)));