Mon Dec 5 15:14:59 CET 2005 Paolo Molaro <lupus@ximian.com>
[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 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Runtime.CompilerServices;
32 using System.Runtime.Remoting.Contexts;
33 using System.Security.Permissions;
34
35 namespace System.Threading
36 {
37         public abstract class WaitHandle : MarshalByRefObject, IDisposable
38         {
39                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
40                 private static extern bool WaitAll_internal(WaitHandle[] handles, int ms, bool exitContext);
41                 
42                 static void CheckArray (WaitHandle [] handles)
43                 {
44                         if (handles == null)
45                                 throw new ArgumentNullException ("waitHandles");
46
47                         int length = handles.Length;
48                         if (length > 64)
49                                 throw new NotSupportedException ("Too many handles");
50
51                         foreach (WaitHandle w in handles) {
52                                 if (w == null)
53                                         throw new ArgumentNullException ("waitHandles", "null handle");
54
55                                 if (w.os_handle == InvalidHandle)
56                                         throw new ArgumentException ("null element found", "waitHandle");
57                         }
58                 }
59                 
60                 public static bool WaitAll(WaitHandle[] waitHandles)
61                 {
62                         CheckArray (waitHandles);
63                         return(WaitAll_internal(waitHandles, Timeout.Infinite, false));
64                 }
65
66                 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
67                 {
68                         CheckArray (waitHandles);
69                         try {
70                                 if (exitContext) SynchronizationAttribute.ExitContext ();
71                                 return(WaitAll_internal(waitHandles, millisecondsTimeout, false));
72                         }
73                         finally {
74                                 if (exitContext) SynchronizationAttribute.EnterContext ();
75                         }
76                 }
77
78                 public static bool WaitAll(WaitHandle[] waitHandles,
79                                            TimeSpan timeout,
80                                            bool exitContext)
81                 {
82                         CheckArray (waitHandles);
83                         long ms = (long) timeout.TotalMilliseconds;
84                         
85                         if (ms < -1 || ms > Int32.MaxValue)
86                                 throw new ArgumentOutOfRangeException ("timeout");
87
88                         try {
89                                 if (exitContext) SynchronizationAttribute.ExitContext ();
90                                 return (WaitAll_internal (waitHandles, (int) ms, exitContext));
91                         }
92                         finally {
93                                 if (exitContext) SynchronizationAttribute.EnterContext ();
94                         }
95                 }
96
97                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
98                 private static extern int WaitAny_internal(WaitHandle[] handles, int ms, bool exitContext);
99
100                 // LAMESPEC: Doesn't specify how to signal failures
101                 public static int WaitAny(WaitHandle[] waitHandles)
102                 {
103                         CheckArray (waitHandles);
104                         return(WaitAny_internal(waitHandles, Timeout.Infinite, false));
105                 }
106
107                 public static int WaitAny(WaitHandle[] waitHandles,
108                                           int millisecondsTimeout,
109                                           bool exitContext)
110                 {
111                         CheckArray (waitHandles);
112                         try {
113                                 if (exitContext) SynchronizationAttribute.ExitContext ();
114                                 return(WaitAny_internal(waitHandles, millisecondsTimeout, exitContext));
115                         }
116                         finally {
117                                 if (exitContext) SynchronizationAttribute.EnterContext ();
118                         }
119                 }
120
121                 public static int WaitAny(WaitHandle[] waitHandles,
122                                           TimeSpan timeout, bool exitContext)
123                 {
124                         CheckArray (waitHandles);
125                         long ms = (long) timeout.TotalMilliseconds;
126                         
127                         if (ms < -1 || ms > Int32.MaxValue)
128                                 throw new ArgumentOutOfRangeException ("timeout");
129
130                         try {
131                                 if (exitContext) SynchronizationAttribute.ExitContext ();
132                                 return (WaitAny_internal(waitHandles, (int) ms, exitContext));
133                         }
134                         finally {
135                                 if (exitContext) SynchronizationAttribute.EnterContext ();
136                         }
137                 }
138
139                 [MonoTODO]
140                 public WaitHandle() {
141                         // FIXME
142                 }
143
144                 public const int WaitTimeout = 258;
145
146                 private IntPtr os_handle = InvalidHandle;
147                 
148                 public virtual IntPtr Handle {
149                         get {
150                                 return(os_handle);
151                         }
152                                 
153                         [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
154                         [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
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                 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 }