Added LwesBinaryInstaller0.1.486.19070.msi
[lwes-dotnet/github-mirror.git] / Org.Lwes / Status.cs
blob04c7921f3f8c6259e9fcffe4e069a89bf06c7b1a
1 //
2 // This file is part of the LWES .NET Binding (LWES.net)
3 //
4 // COPYRIGHT© 2009, Phillip Clark (phillip[at*flitbit[dot*org)
5 // original .NET implementation
6 //
7 // LWES.net is free software: you can redistribute it and/or modify
8 // it under the terms of the Lesser GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
12 // LWES.net is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // Lesser GNU General Public License for more details.
17 // You should have received a copy of the Lesser GNU General Public License
18 // along with LWES.net. If not, see <http://www.gnu.org/licenses/>.
20 namespace Org.Lwes
22 using System;
23 using System.Threading;
25 /// <summary>
26 /// Utility structure for performing and tracking threadsafe state transitions.
27 /// </summary>
28 /// <typeparam name="E">State type E (should be an enum)</typeparam>
29 public struct Status<E>
31 #region Fields
33 int _status;
35 #endregion Fields
37 #region Constructors
39 /// <summary>
40 /// Creates a new instance.
41 /// </summary>
42 /// <param name="initialialState">Initial state</param>
43 public Status(E initialialState)
45 _status = Convert.ToInt32(initialialState);
48 #endregion Constructors
50 #region Properties
52 /// <summary>
53 /// Accesses the current state.
54 /// </summary>
55 public E CurrentState
57 get { return (E)Enum.ToObject(typeof(E), Thread.VolatileRead(ref _status)); }
60 #endregion Properties
62 #region Methods
64 /// <summary>
65 /// Determines if the current state is greater than the comparand.
66 /// </summary>
67 /// <param name="comparand">comparand</param>
68 /// <returns><em>true</em> if the current state is greater than <paramref name="comparand"/>; otherwise <em>false</em></returns>
69 public bool IsGreaterThan(E comparand)
71 return Thread.VolatileRead(ref _status) > Convert.ToInt32(comparand);
74 /// <summary>
75 /// Determines if the current state is less than the comparand.
76 /// </summary>
77 /// <param name="comparand">comparand</param>
78 /// <returns><em>true</em> if the current state is less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
79 public bool IsLessThan(E comparand)
81 return Thread.VolatileRead(ref _status) < Convert.ToInt32(comparand);
84 /// <summary>
85 /// Transitions to the given state.
86 /// </summary>
87 /// <param name="value">the target state</param>
88 public void SetState(E value)
90 Thread.VolatileWrite(ref _status, Convert.ToInt32(value));
93 /// <summary>
94 /// Performs a state transition if the current state compares greater than the <paramref name="comparand"/>
95 /// </summary>
96 /// <param name="value">the target state</param>
97 /// <param name="comparand">comparand state</param>
98 /// <returns><em>true</em> if the current state compares greater than <paramref name="comparand"/>; otherwise <em>false</em></returns>
99 public bool SetStateIfGreaterThan(E value, E comparand)
101 int c = Convert.ToInt32(comparand);
102 int v = Convert.ToInt32(value);
104 int init, fin = Thread.VolatileRead(ref _status);
105 while (true)
107 if (fin < c) return false;
109 init = fin;
110 fin = Interlocked.CompareExchange(ref _status, v, init);
111 if (fin == init) return true;
115 /// <summary>
116 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
117 /// </summary>
118 /// <param name="value">the target state</param>
119 /// <param name="comparand">comparand state</param>
120 /// <returns><em>true</em> if the current state compares less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
121 public bool SetStateIfLessThan(E value, E comparand)
123 int c = Convert.ToInt32(comparand);
124 int v = Convert.ToInt32(value);
126 int init, fin = Thread.VolatileRead(ref _status);
127 while (true)
129 if (fin > c) return false;
131 init = fin;
132 fin = Interlocked.CompareExchange(ref _status, v, init);
133 if (fin == init) return true;
137 /// <summary>
138 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
139 /// </summary>
140 /// <param name="value">the target state</param>
141 /// <param name="comparand">comparand state</param>
142 /// <param name="actionOnSuccess">An action to be performed if the state transition succeeds</param>
143 /// <returns><em>true</em> if the current state compares less than <paramref name="comparand"/>; otherwise <em>false</em></returns>
144 public bool SetStateIfLessThan(E value, E comparand, Action actionOnSuccess)
146 if (actionOnSuccess == null) throw new ArgumentNullException("actionOnSuccess");
147 if (SetStateIfLessThan(value, comparand))
149 actionOnSuccess();
150 return true;
152 return false;
155 /// <summary>
156 /// Toggles between the toggle state and the desired state - with
157 /// a spin-wait if necessary.
158 /// </summary>
159 /// <param name="desired">desired state</param>
160 /// <param name="toggle">state from which the desired state can toggle</param>
161 /// <returns><em>true</em> if the state transitions to the desired state from the toggle state; otherwise <em>false</em></returns>
162 public bool SpinToggleState(E desired, E toggle)
164 int d = Convert.ToInt32(desired);
165 int t = Convert.ToInt32(toggle);
167 spin:
168 int r = Interlocked.CompareExchange(ref _status, d, t);
169 // If the state was the toggle state then we're successful and done...
170 if (r == t) return true;
171 // otherwise if the result is anything but the desired state we're
172 // unsuccessful and done...
173 if (r != d) return false;
174 // otherwise we spin
175 goto spin;
178 /// <summary>
179 /// Perfroms a spinwait until the current state equals the target state.
180 /// </summary>
181 /// <param name="targetState">the target state</param>
182 /// <param name="loopAction">An action to perform inside the spin cycle</param>
183 public void SpinWaitForState(E targetState, Action loopAction)
185 int state = Convert.ToInt32(targetState);
186 while (Thread.VolatileRead(ref _status) != state)
188 loopAction();
192 /// <summary>
193 /// Tries to transition the state
194 /// </summary>
195 /// <param name="value">the target state</param>
196 /// <param name="comparand">comparand state must match current state</param>
197 /// <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>
198 public bool TryTransition(E value, E comparand)
200 int c = Convert.ToInt32(comparand);
201 return Interlocked.CompareExchange(ref _status, Convert.ToInt32(value), c) == c;
204 /// <summary>
205 /// Tries to transition the state. Upon success executes the action given.
206 /// </summary>
207 /// <param name="value">the target state</param>
208 /// <param name="comparand">comparand state must match current state</param>
209 /// <param name="actionOnSuccess">action to perform if the state transition is successful</param>
210 /// <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>
211 public bool TryTransition(E value, E comparand, Action actionOnSuccess)
213 if (actionOnSuccess == null) throw new ArgumentNullException("actionOnSuccess");
214 if (TryTransition(value, comparand))
216 actionOnSuccess();
217 return true;
219 return false;
222 internal E CompareExchange(E value, E comparand)
224 return
225 (E)Enum.ToObject(typeof(E), Interlocked.CompareExchange(ref _status, Convert.ToInt32(value), Convert.ToInt32(comparand)));
229 #endregion Methods