4 using System
.Threading
;
7 /// Utility structure for performing and tracking threadsafe state transitions.
9 /// <typeparam name="E">State type E (should be an enum)</typeparam>
10 public struct Status
<E
>
21 /// Creates a new instance.
23 /// <param name="initialialState">Initial state</param>
24 public Status(E initialialState
)
26 _status
= Convert
.ToInt32(initialialState
);
29 #endregion Constructors
34 /// Accesses the current state.
38 get { return (E)Enum.ToObject(typeof(E), Thread.VolatileRead(ref _status)); }
46 /// Determines if the current state is greater than the comparand.
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
);
56 /// Determines if the current state is less than the comparand.
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
);
66 /// Transitions to the given state.
68 /// <param name="value">the target state</param>
69 public void SetState(E
value)
71 Thread
.VolatileWrite(ref _status
, Convert
.ToInt32(value));
75 /// Performs a state transition if the current state compares greater than the <paramref name="comparand"/>
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
);
88 if (fin
< c
) return false;
91 fin
= Interlocked
.CompareExchange(ref _status
, v
, init
);
92 if (fin
== init
) return true;
97 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
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
);
110 if (fin
> c
) return false;
113 fin
= Interlocked
.CompareExchange(ref _status
, v
, init
);
114 if (fin
== init
) return true;
119 /// Performs a state transition if the current state compares less than the <paramref name="comparand"/>
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
))
137 /// Toggles between the toggle state and the desired state - with
138 /// a spin-wait if necessary.
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
);
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;
160 /// Perfroms a spinwait until the current state equals the target state.
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
)
174 /// Tries to transition the state
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
;
186 /// Tries to transition the state. Upon success executes the action given.
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
))
205 internal E
CompareExchange(E
value, E comparand
)
208 (E
)Enum
.ToObject(typeof(E
), Interlocked
.CompareExchange(ref _status
, Convert
.ToInt32(value), Convert
.ToInt32(comparand
)));