This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / corlib / System.Threading / WaitHandle.cs
1 //
2 // System.Threading.WaitHandle.cs
3 //
4 // Author:
5 //      Dick Porter (dick@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com
7 //
8 // (C) 2002,2003 Ximian, Inc.   (http://www.ximian.com)
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Runtime.CompilerServices;
35 using System.Runtime.Remoting.Contexts;
36
37 namespace System.Threading
38 {
39         public abstract class WaitHandle : MarshalByRefObject, IDisposable
40         {
41                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
42                 private static extern bool WaitAll_internal(WaitHandle[] handles, int ms, bool exitContext);
43                 
44                 static void CheckArray (WaitHandle [] handles)
45                 {
46                         if (handles == null)
47                                 throw new ArgumentNullException ("waitHandles");
48
49                         int length = handles.Length;
50                         if (length > 64)
51                                 throw new NotSupportedException ("Too many handles");
52
53                         foreach (WaitHandle w in handles) {
54                                 if (w == null)
55                                         throw new ArgumentNullException ("waitHandles", "null handle");
56
57                                 if (w.os_handle == InvalidHandle)
58                                         throw new ArgumentException ("null element found", "waitHandle");
59                         }
60                 }
61                 
62                 public static bool WaitAll(WaitHandle[] waitHandles)
63                 {
64                         CheckArray (waitHandles);
65                         return(WaitAll_internal(waitHandles, Timeout.Infinite, false));
66                 }
67
68                 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
69                 {
70                         CheckArray (waitHandles);
71                         try {
72                                 if (exitContext) SynchronizationAttribute.ExitContext ();
73                                 return(WaitAll_internal(waitHandles, millisecondsTimeout, false));
74                         }
75                         finally {
76                                 if (exitContext) SynchronizationAttribute.EnterContext ();
77                         }
78                 }
79
80                 public static bool WaitAll(WaitHandle[] waitHandles,
81                                            TimeSpan timeout,
82                                            bool exitContext)
83                 {
84                         CheckArray (waitHandles);
85                         long ms = (long) timeout.TotalMilliseconds;
86                         
87                         if (ms < -1 || ms > Int32.MaxValue)
88                                 throw new ArgumentOutOfRangeException ("timeout");
89
90                         try {
91                                 if (exitContext) SynchronizationAttribute.ExitContext ();
92                                 return (WaitAll_internal (waitHandles, (int) ms, exitContext));
93                         }
94                         finally {
95                                 if (exitContext) SynchronizationAttribute.EnterContext ();
96                         }
97                 }
98
99                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
100                 private static extern int WaitAny_internal(WaitHandle[] handles, int ms, bool exitContext);
101
102                 // LAMESPEC: Doesn't specify how to signal failures
103                 public static int WaitAny(WaitHandle[] waitHandles)
104                 {
105                         CheckArray (waitHandles);
106                         return(WaitAny_internal(waitHandles, Timeout.Infinite, false));
107                 }
108
109                 public static int WaitAny(WaitHandle[] waitHandles,
110                                           int millisecondsTimeout,
111                                           bool exitContext)
112                 {
113                         CheckArray (waitHandles);
114                         try {
115                                 if (exitContext) SynchronizationAttribute.ExitContext ();
116                                 return(WaitAny_internal(waitHandles, millisecondsTimeout, exitContext));
117                         }
118                         finally {
119                                 if (exitContext) SynchronizationAttribute.EnterContext ();
120                         }
121                 }
122
123                 public static int WaitAny(WaitHandle[] waitHandles,
124                                           TimeSpan timeout, bool exitContext)
125                 {
126                         CheckArray (waitHandles);
127                         long ms = (long) timeout.TotalMilliseconds;
128                         
129                         if (ms < -1 || ms > Int32.MaxValue)
130                                 throw new ArgumentOutOfRangeException ("timeout");
131
132                         try {
133                                 if (exitContext) SynchronizationAttribute.ExitContext ();
134                                 return (WaitAny_internal(waitHandles, (int) ms, exitContext));
135                         }
136                         finally {
137                                 if (exitContext) SynchronizationAttribute.EnterContext ();
138                         }
139                 }
140
141                 [MonoTODO]
142                 public WaitHandle() {
143                         // FIXME
144                 }
145
146                 public const int WaitTimeout = 258;
147
148                 private IntPtr os_handle = InvalidHandle;
149                 
150                 public virtual IntPtr Handle {
151                         get {
152                                 return(os_handle);
153                         }
154                                 
155                         set {
156                                 os_handle=value;
157                         }
158                 }
159
160                 public virtual void Close() {
161                         Dispose(true);
162                         GC.SuppressFinalize (this);
163                 }
164
165                 internal void CheckDisposed ()
166                 {
167                         if (disposed || os_handle == InvalidHandle)
168                                 throw new ObjectDisposedException (GetType ().FullName);
169                 }
170                 
171                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
172                 private extern bool WaitOne_internal(IntPtr handle, int ms, bool exitContext);
173
174                 public virtual bool WaitOne()
175                 {
176                         CheckDisposed ();
177                         return(WaitOne_internal(os_handle, Timeout.Infinite, false));
178                 }
179
180                 public virtual bool WaitOne(int millisecondsTimeout, bool exitContext)
181                 {
182                         CheckDisposed ();
183                         try {
184                                 if (exitContext) SynchronizationAttribute.ExitContext ();
185                                 return(WaitOne_internal(os_handle, millisecondsTimeout, exitContext));
186                         }
187                         finally {
188                                 if (exitContext) SynchronizationAttribute.EnterContext ();
189                         }
190                 }
191
192                 public virtual bool WaitOne(TimeSpan timeout, bool exitContext)
193                 {
194                         CheckDisposed ();
195                         long ms = (long) timeout.TotalMilliseconds;
196                         if (ms < -1 || ms > Int32.MaxValue)
197                                 throw new ArgumentOutOfRangeException ("timeout");
198
199                         try {
200                                 if (exitContext) SynchronizationAttribute.ExitContext ();
201                                 return (WaitOne_internal(os_handle, (int) ms, exitContext));
202                         }
203                         finally {
204                                 if (exitContext) SynchronizationAttribute.EnterContext ();
205                         }
206                 }
207
208                 protected static readonly IntPtr InvalidHandle = IntPtr.Zero;
209
210                 private bool disposed = false;
211
212                 void IDisposable.Dispose() {
213                         Dispose(true);
214                         // Take yourself off the Finalization queue
215                         GC.SuppressFinalize(this);
216                 }
217                 
218                 protected virtual void Dispose(bool explicitDisposing) {
219                         // Check to see if Dispose has already been called.
220                         if (!disposed) {
221                                 disposed=true;
222                                 if (os_handle == InvalidHandle)
223                                         return;
224
225                                 lock (this) {
226                                         if (os_handle != InvalidHandle) {
227                                                 NativeEventCalls.CloseEvent_internal (os_handle);
228                                                 os_handle = InvalidHandle;
229                                         }
230                                 }
231                         }
232                 }
233
234                 ~WaitHandle() {
235                         Dispose(false);
236                 }
237         }
238 }