mscorlib(4.0.0.0) API with additions
ManualResetEventSlim.cs
1 using System.Diagnostics;
4 
5 namespace System.Threading
6 {
8  [ComVisible(false)]
9  [DebuggerDisplay("Set = {IsSet}")]
10  [__DynamicallyInvokable]
11  [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
13  {
14  private const int DEFAULT_SPIN_SP = 1;
15 
16  private const int DEFAULT_SPIN_MP = 10;
17 
18  private volatile object m_lock;
19 
20  private volatile ManualResetEvent m_eventObj;
21 
22  private volatile int m_combinedState;
23 
24  private const int SignalledState_BitMask = int.MinValue;
25 
26  private const int SignalledState_ShiftCount = 31;
27 
28  private const int Dispose_BitMask = 1073741824;
29 
30  private const int SpinCountState_BitMask = 1073217536;
31 
32  private const int SpinCountState_ShiftCount = 19;
33 
34  private const int SpinCountState_MaxValue = 2047;
35 
36  private const int NumWaitersState_BitMask = 524287;
37 
38  private const int NumWaitersState_ShiftCount = 0;
39 
40  private const int NumWaitersState_MaxValue = 524287;
41 
42  private static Action<object> s_cancellationTokenCallback = CancellationTokenCallback;
43 
46  [__DynamicallyInvokable]
47  public WaitHandle WaitHandle
48  {
49  [__DynamicallyInvokable]
50  get
51  {
52  ThrowIfDisposed();
53  if (m_eventObj == null)
54  {
55  LazyInitializeEvent();
56  }
57  return m_eventObj;
58  }
59  }
60 
63  [__DynamicallyInvokable]
64  public bool IsSet
65  {
66  [__DynamicallyInvokable]
67  get
68  {
69  return ExtractStatePortion(m_combinedState, int.MinValue) != 0;
70  }
71  private set
72  {
73  UpdateStateAtomically((value ? 1 : 0) << 31, int.MinValue);
74  }
75  }
76 
79  [__DynamicallyInvokable]
80  public int SpinCount
81  {
82  [__DynamicallyInvokable]
83  get
84  {
85  return ExtractStatePortionAndShiftRight(m_combinedState, 1073217536, 19);
86  }
87  private set
88  {
89  m_combinedState = ((m_combinedState & -1073217537) | (value << 19));
90  }
91  }
92 
93  private int Waiters
94  {
95  get
96  {
97  return ExtractStatePortionAndShiftRight(m_combinedState, 524287, 0);
98  }
99  set
100  {
101  if (value >= 524287)
102  {
103  throw new InvalidOperationException(string.Format(Environment.GetResourceString("ManualResetEventSlim_ctor_TooManyWaiters"), 524287));
104  }
105  UpdateStateAtomically(value, 524287);
106  }
107  }
108 
110  [__DynamicallyInvokable]
112  : this(initialState: false)
113  {
114  }
115 
118  [__DynamicallyInvokable]
119  public ManualResetEventSlim(bool initialState)
120  {
121  Initialize(initialState, 10);
122  }
123 
129  [__DynamicallyInvokable]
130  public ManualResetEventSlim(bool initialState, int spinCount)
131  {
132  if (spinCount < 0)
133  {
134  throw new ArgumentOutOfRangeException("spinCount");
135  }
136  if (spinCount > 2047)
137  {
138  throw new ArgumentOutOfRangeException("spinCount", string.Format(Environment.GetResourceString("ManualResetEventSlim_ctor_SpinCountOutOfRange"), 2047));
139  }
140  Initialize(initialState, spinCount);
141  }
142 
143  private void Initialize(bool initialState, int spinCount)
144  {
145  m_combinedState = (initialState ? int.MinValue : 0);
146  SpinCount = (PlatformHelper.IsSingleProcessor ? 1 : spinCount);
147  }
148 
149  private void EnsureLockObjectCreated()
150  {
151  if (m_lock == null)
152  {
153  object value = new object();
154  Interlocked.CompareExchange(ref m_lock, value, null);
155  }
156  }
157 
158  private bool LazyInitializeEvent()
159  {
160  bool isSet = IsSet;
161  ManualResetEvent manualResetEvent = new ManualResetEvent(isSet);
162  if (Interlocked.CompareExchange(ref m_eventObj, manualResetEvent, null) != null)
163  {
164  manualResetEvent.Close();
165  return false;
166  }
167  bool isSet2 = IsSet;
168  if (isSet2 != isSet)
169  {
170  lock (manualResetEvent)
171  {
172  if (m_eventObj == manualResetEvent)
173  {
174  manualResetEvent.Set();
175  }
176  }
177  }
178  return true;
179  }
180 
182  [__DynamicallyInvokable]
183  public void Set()
184  {
185  Set(duringCancellation: false);
186  }
187 
188  private void Set(bool duringCancellation)
189  {
190  IsSet = true;
191  if (Waiters > 0)
192  {
193  lock (m_lock)
194  {
195  Monitor.PulseAll(m_lock);
196  }
197  }
198  ManualResetEvent eventObj = m_eventObj;
199  if (eventObj != null && !duringCancellation)
200  {
201  lock (eventObj)
202  {
203  if (m_eventObj != null)
204  {
205  m_eventObj.Set();
206  }
207  }
208  }
209  }
210 
213  [__DynamicallyInvokable]
214  public void Reset()
215  {
216  ThrowIfDisposed();
217  if (m_eventObj != null)
218  {
219  m_eventObj.Reset();
220  }
221  IsSet = false;
222  }
223 
227  [__DynamicallyInvokable]
228  public void Wait()
229  {
230  Wait(-1, default(CancellationToken));
231  }
232 
239  [__DynamicallyInvokable]
240  public void Wait(CancellationToken cancellationToken)
241  {
242  Wait(-1, cancellationToken);
243  }
244 
253  [__DynamicallyInvokable]
254  public bool Wait(TimeSpan timeout)
255  {
256  long num = (long)timeout.TotalMilliseconds;
257  if (num < -1 || num > int.MaxValue)
258  {
259  throw new ArgumentOutOfRangeException("timeout");
260  }
261  return Wait((int)num, default(CancellationToken));
262  }
263 
275  [__DynamicallyInvokable]
276  public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
277  {
278  long num = (long)timeout.TotalMilliseconds;
279  if (num < -1 || num > int.MaxValue)
280  {
281  throw new ArgumentOutOfRangeException("timeout");
282  }
283  return Wait((int)num, cancellationToken);
284  }
285 
294  [__DynamicallyInvokable]
295  public bool Wait(int millisecondsTimeout)
296  {
297  return Wait(millisecondsTimeout, default(CancellationToken));
298  }
299 
311  [__DynamicallyInvokable]
312  public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
313  {
314  ThrowIfDisposed();
315  cancellationToken.ThrowIfCancellationRequested();
316  if (millisecondsTimeout < -1)
317  {
318  throw new ArgumentOutOfRangeException("millisecondsTimeout");
319  }
320  if (!IsSet)
321  {
322  if (millisecondsTimeout == 0)
323  {
324  return false;
325  }
326  uint startTime = 0u;
327  bool flag = false;
328  int num = millisecondsTimeout;
329  if (millisecondsTimeout != -1)
330  {
331  startTime = TimeoutHelper.GetTime();
332  flag = true;
333  }
334  int num2 = 10;
335  int num3 = 5;
336  int num4 = 20;
337  int spinCount = SpinCount;
338  for (int i = 0; i < spinCount; i++)
339  {
340  if (IsSet)
341  {
342  return true;
343  }
344  if (i < num2)
345  {
346  if (i == num2 / 2)
347  {
348  Thread.Yield();
349  }
350  else
351  {
352  Thread.SpinWait(PlatformHelper.ProcessorCount * (4 << i));
353  }
354  }
355  else if (i % num4 == 0)
356  {
357  Thread.Sleep(1);
358  }
359  else if (i % num3 == 0)
360  {
361  Thread.Sleep(0);
362  }
363  else
364  {
365  Thread.Yield();
366  }
367  if (i >= 100 && i % 10 == 0)
368  {
369  cancellationToken.ThrowIfCancellationRequested();
370  }
371  }
372  EnsureLockObjectCreated();
373  using (cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCallback, this))
374  {
375  lock (m_lock)
376  {
377  while (!IsSet)
378  {
379  cancellationToken.ThrowIfCancellationRequested();
380  if (flag)
381  {
382  num = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
383  if (num <= 0)
384  {
385  return false;
386  }
387  }
388  Waiters++;
389  if (IsSet)
390  {
391  Waiters--;
392  return true;
393  }
394  try
395  {
396  if (!Monitor.Wait(m_lock, num))
397  {
398  return false;
399  }
400  }
401  finally
402  {
403  Waiters--;
404  }
405  }
406  }
407  }
408  }
409  return true;
410  }
411 
413  [__DynamicallyInvokable]
414  public void Dispose()
415  {
416  Dispose(disposing: true);
417  GC.SuppressFinalize(this);
418  }
419 
422  [__DynamicallyInvokable]
423  protected virtual void Dispose(bool disposing)
424  {
425  if ((m_combinedState & 0x40000000) != 0)
426  {
427  return;
428  }
429  m_combinedState |= 1073741824;
430  if (disposing)
431  {
432  ManualResetEvent eventObj = m_eventObj;
433  if (eventObj != null)
434  {
435  lock (eventObj)
436  {
437  eventObj.Close();
438  m_eventObj = null;
439  }
440  }
441  }
442  }
443 
444  private void ThrowIfDisposed()
445  {
446  if ((m_combinedState & 0x40000000) != 0)
447  {
448  throw new ObjectDisposedException(Environment.GetResourceString("ManualResetEventSlim_Disposed"));
449  }
450  }
451 
452  private static void CancellationTokenCallback(object obj)
453  {
454  ManualResetEventSlim manualResetEventSlim = obj as ManualResetEventSlim;
455  lock (manualResetEventSlim.m_lock)
456  {
457  Monitor.PulseAll(manualResetEventSlim.m_lock);
458  }
459  }
460 
461  private void UpdateStateAtomically(int newBits, int updateBitsMask)
462  {
463  SpinWait spinWait = default(SpinWait);
464  while (true)
465  {
466  int combinedState = m_combinedState;
467  int value = (combinedState & ~updateBitsMask) | newBits;
468  if (Interlocked.CompareExchange(ref m_combinedState, value, combinedState) == combinedState)
469  {
470  break;
471  }
472  spinWait.SpinOnce();
473  }
474  }
475 
476  private static int ExtractStatePortionAndShiftRight(int state, int mask, int rightBitShiftCount)
477  {
478  return (int)((uint)(state & mask) >> rightBitShiftCount);
479  }
480 
481  private static int ExtractStatePortion(int state, int mask)
482  {
483  return state & mask;
484  }
485  }
486 }
void Wait(CancellationToken cancellationToken)
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim receives a signal...
void Dispose()
Releases all resources used by the current instance of the T:System.Threading.ManualResetEventSlim cl...
Propagates notification that operations should be canceled.
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
Definition: WaitHandle.cs:15
void ThrowIfCancellationRequested()
Throws a T:System.OperationCanceledException if this token has had cancellation requested.
static void PulseAll(object obj)
Notifies all waiting threads of a change in the object's state.
Definition: Monitor.cs:299
static void SuppressFinalize(object obj)
Requests that the common language runtime not call the finalizer for the specified object.
Definition: GC.cs:308
virtual void Dispose(bool disposing)
Releases the unmanaged resources used by the T:System.Threading.ManualResetEventSlim,...
Provides a mechanism for releasing unmanaged resources.To browse the .NET Framework source code for t...
Definition: IDisposable.cs:8
Definition: __Canon.cs:3
The exception that is thrown when the value of an argument is outside the allowable range of values a...
Provides a mechanism that synchronizes access to objects.
Definition: Monitor.cs:13
static bool Wait(object obj, int millisecondsTimeout, bool exitContext)
Releases the lock on an object and blocks the current thread until it reacquires the lock....
Definition: Monitor.cs:201
bool Wait(TimeSpan timeout)
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim is set,...
double TotalMilliseconds
Gets the value of the current T:System.TimeSpan structure expressed in whole and fractional milliseco...
Definition: TimeSpan.cs:180
ManualResetEventSlim(bool initialState)
Initializes a new instance of the T:System.Threading.ManualResetEventSlim class with a Boolean value ...
ManualResetEventSlim()
Initializes a new instance of the T:System.Threading.ManualResetEventSlim class with an initial state...
void Wait()
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim is set.
The exception that is thrown when an operation is performed on a disposed object.
SecurityAction
Specifies the security actions that can be performed using declarative security.
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim is set,...
void Set()
Sets the state of the event to signaled, which allows one or more threads waiting on the event to pro...
bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim is set,...
Notifies one or more waiting threads that an event has occurred. This class cannot be inherited.
Provides a slimmed down version of T:System.Threading.ManualResetEvent.
bool? IsSet
Gets whether the event is set.
virtual void Close()
Releases all resources held by the current T:System.Threading.WaitHandle.
Definition: WaitHandle.cs:714
ManualResetEventSlim(bool initialState, int spinCount)
Initializes a new instance of the T:System.Threading.ManualResetEventSlim class with a Boolean value ...
Controls the system garbage collector, a service that automatically reclaims unused memory.
Definition: GC.cs:11
Represents a time interval.To browse the .NET Framework source code for this type,...
Definition: TimeSpan.cs:12
The exception that is thrown when a method call is invalid for the object's current state.
void Reset()
Sets the state of the event to nonsignaled, which causes threads to block.
static void Sleep(int millisecondsTimeout)
Suspends the current thread for the specified number of milliseconds.
Definition: Thread.cs:746
int SpinCount
Gets the number of spin waits that will occur before falling back to a kernel-based wait operation.
static bool Yield()
Causes the calling thread to yield execution to another thread that is ready to run on the current pr...
Definition: Thread.cs:797
bool Wait(int millisecondsTimeout)
Blocks the current thread until the current T:System.Threading.ManualResetEventSlim is set,...
static void SpinWait(int iterations)
Causes a thread to wait the number of times defined by the iterations parameter.
Definition: Thread.cs:779
Creates and controls a thread, sets its priority, and gets its status.
Definition: Thread.cs:18