2 // This file is part of the LWES .NET Binding (LWES.net)
4 // COPYRIGHT© 2009, Phillip Clark (cerebralkungfu[at*g mail[dot*com)
5 // original .NET implementation
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/>.
23 using System
.Threading
;
26 /// Utility structure for performing and tracking threadsafe state transitions.
28 /// <typeparam name="E">State type E (should be an enum)</typeparam>
29 public struct Status
<E
>
40 /// Creates a new instance.
42 /// <param name="initialialState">Initial state</param>
43 public Status(E initialialState
)
45 _status
= Convert
.ToInt32(initialialState
);
48 #endregion Constructors
53 /// Accesses the current state.
57 get { return (E)Enum.ToObject(typeof(E), Thread.VolatileRead(ref _status)); }
65 /// Determines if the current state is greater than the comparand.
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
);
75 /// Determines if the current state is less than the comparand.
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
);
85 /// Transitions to the given state.
87 /// <param name="value">the target state</param>
88 public void SetState(E
value)
90 Thread
.VolatileWrite(ref _status
, Convert
.ToInt32(value));
94 /// Performs a state transition if the current state compares greater than the <paramref name="comparand"/>
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
);
107 if (fin
< c
) return false;
110 fin
= Interlocked
.CompareExchange(ref _status
, v
, init
);
111 if (fin
== init
) return true;
116 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
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
);
129 if (fin
> c
) return false;
132 fin
= Interlocked
.CompareExchange(ref _status
, v
, init
);
133 if (fin
== init
) return true;
138 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
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
))
156 /// Toggles between the toggle state and the desired state - with
157 /// a spin-wait if necessary.
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
);
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;
179 /// Perfroms a spinwait until the current state equals the target state.
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
)
193 /// Tries to transition the state
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
;
205 /// Tries to transition the state. Upon success executes the action given.
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
))
222 internal E
CompareExchange(E
value, E comparand
)
225 (E
)Enum
.ToObject(typeof(E
), Interlocked
.CompareExchange(ref _status
, Convert
.ToInt32(value), Convert
.ToInt32(comparand
)));