CountdownEvent.cs
Go to the documentation of this file.
1 // CountdownEvent.cs
2 //
3 // Authors:
4 // Marek Safar <marek.safar@gmail.com>
5 //
6 // Copyright (c) 2008 Jérémie "Garuma" Laval
7 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 //
27 //
28 
29 #if NET_4_0
30 
31 namespace System.Threading
32 {
33  [System.Diagnostics.DebuggerDisplayAttribute ("Initial Count={InitialCount}, Current Count={CurrentCount}")]
34  public class CountdownEvent : IDisposable
35  {
36  int initialCount;
37  int initial;
39 
40  public CountdownEvent (int initialCount)
41  {
42  if (initialCount < 0)
43  throw new ArgumentOutOfRangeException ("initialCount");
44 
45  evt = new ManualResetEventSlim (initialCount == 0);
46  this.initial = this.initialCount = initialCount;
47  }
48 
49  public int CurrentCount {
50  get {
51  return initialCount;
52  }
53  }
54 
55  public int InitialCount {
56  get {
57  return initial;
58  }
59  }
60 
61  public bool IsSet {
62  get {
63  return initialCount == 0;
64  }
65  }
66 
67  public WaitHandle WaitHandle {
68  get {
69  return evt.WaitHandle;
70  }
71  }
72 
73  public bool Signal ()
74  {
75  return Signal (1);
76  }
77 
78  public bool Signal (int signalCount)
79  {
80  if (signalCount <= 0)
81  throw new ArgumentOutOfRangeException ("signalCount");
82 
83  CheckDisposed ();
84 
85  int newValue;
86  if (!ApplyOperation (-signalCount, out newValue))
87  throw new InvalidOperationException ("The event is already set");
88 
89  if (newValue == 0) {
90  evt.Set ();
91  return true;
92  }
93 
94  return false;
95  }
96 
97  public void AddCount ()
98  {
99  AddCount (1);
100  }
101 
102  public void AddCount (int signalCount)
103  {
104  if (!TryAddCount (signalCount))
105  throw new InvalidOperationException ("The event is already signaled and cannot be incremented");
106  }
107 
108  public bool TryAddCount ()
109  {
110  return TryAddCount (1);
111  }
112 
113  public bool TryAddCount (int signalCount)
114  {
115  if (signalCount <= 0)
116  throw new ArgumentOutOfRangeException ("signalCount");
117 
118  CheckDisposed ();
119 
120  int temp;
121  return ApplyOperation (signalCount, out temp);
122  }
123 
124  bool ApplyOperation (int num, out int newValue)
125  {
126  int oldCount;
127 
128  do {
129  oldCount = initialCount;
130  if (oldCount == 0) {
131  newValue = 0;
132  return false;
133  }
134 
135  newValue = oldCount + num;
136 
137  if (newValue < 0)
138  return false;
139  } while (Interlocked.CompareExchange (ref initialCount, newValue, oldCount) != oldCount);
140 
141  return true;
142  }
143 
144  public void Wait ()
145  {
146  evt.Wait ();
147  }
148 
149  public void Wait (CancellationToken cancellationToken)
150  {
151  evt.Wait (cancellationToken);
152  }
153 
154  public bool Wait (int millisecondsTimeout)
155  {
156  return evt.Wait (millisecondsTimeout);
157  }
158 
159  public bool Wait(TimeSpan timeout)
160  {
161  return evt.Wait (timeout);
162  }
163 
164  public bool Wait (int millisecondsTimeout, CancellationToken cancellationToken)
165  {
166  return evt.Wait (millisecondsTimeout, cancellationToken);
167  }
168 
169  public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
170  {
171  return evt.Wait (timeout, cancellationToken);
172  }
173 
174  public void Reset ()
175  {
176  Reset (initial);
177  }
178 
179  public void Reset (int count)
180  {
181  if (count < 0)
182  throw new ArgumentOutOfRangeException ("count");
183 
184  CheckDisposed ();
185 
186  initialCount = initial = count;
187  if (count == 0)
188  evt.Set ();
189  else
190  evt.Reset ();
191  }
192 
193  public void Dispose ()
194  {
195  Dispose (true);
196  }
197 
198  protected virtual void Dispose (bool disposing)
199  {
200  if (disposing)
201  evt.Dispose ();
202  }
203 
204  void CheckDisposed ()
205  {
206  if (evt.disposed.Value)
207  throw new ObjectDisposedException ("CountdownEvent");
208  }
209  }
210 }
211 #endif
CountdownEvent(int initialCount)
bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
bool TryAddCount(int signalCount)
void Wait(CancellationToken cancellationToken)
virtual void Dispose(bool disposing)
bool Signal(int signalCount)
bool Wait(TimeSpan timeout)
void AddCount(int signalCount)
bool Wait(int millisecondsTimeout)
bool Wait(TimeSpan timeout, CancellationToken cancellationToken)