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