2 // System.Threading.Monitor.cs
5 // Dick Porter (dick@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Runtime.CompilerServices;
34 using System.Runtime.Remoting.Contexts;
35 using System.Runtime.ConstrainedExecution;
36 using System.Runtime.InteropServices;
38 namespace System.Threading
41 public static class Monitor
43 // Grabs the mutex on object 'obj', with a maximum
44 // wait time 'ms' but doesn't block - if it can't get
45 // the lock it returns false, true if it can
46 [MethodImplAttribute(MethodImplOptions.InternalCall)]
47 private extern static bool Monitor_try_enter(object obj, int ms);
49 // Enter/Exit are implemented directly as icalls for performance reasons
51 // Acquires the mutex on object 'obj'
52 [MethodImplAttribute(MethodImplOptions.InternalCall)]
53 public extern static void Enter(object obj);
55 // Releases the mutex on object 'obj'
56 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 public extern static void Exit(object obj);
60 // Signals one of potentially many objects waiting on
62 [MethodImplAttribute(MethodImplOptions.InternalCall)]
63 private extern static void Monitor_pulse(object obj);
65 // Checks whether object 'obj' is currently synchronised
66 [MethodImplAttribute(MethodImplOptions.InternalCall)]
67 private extern static bool Monitor_test_synchronised(object obj);
69 public static void Pulse(object obj) {
71 throw new ArgumentNullException("obj");
73 if(Monitor_test_synchronised(obj)==false) {
74 throw new SynchronizationLockException("Object is not synchronized");
80 // Signals all of potentially many objects waiting on
82 [MethodImplAttribute(MethodImplOptions.InternalCall)]
83 private extern static void Monitor_pulse_all(object obj);
85 public static void PulseAll(object obj) {
87 throw new ArgumentNullException("obj");
89 if(Monitor_test_synchronised(obj)==false) {
90 throw new SynchronizationLockException("Object is not synchronized");
93 Monitor_pulse_all(obj);
96 public static bool TryEnter (object obj)
98 return TryEnter (obj, 0);
101 public static bool TryEnter (object obj, int millisecondsTimeout)
104 throw new ArgumentNullException ("obj");
106 if (millisecondsTimeout == Timeout.Infinite) {
111 if (millisecondsTimeout < 0)
112 throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");
114 return Monitor_try_enter (obj, millisecondsTimeout);
117 public static bool TryEnter (object obj, TimeSpan timeout)
119 long ms = (long) timeout.TotalMilliseconds;
120 if (ms < Timeout.Infinite || ms > Int32.MaxValue)
121 throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
123 return TryEnter (obj, (int) ms);
126 // Waits for a signal on object 'obj' with maximum
127 // wait time 'ms'. Returns true if the object was
128 // signalled, false if it timed out
129 [MethodImplAttribute(MethodImplOptions.InternalCall)]
130 private extern static bool Monitor_wait(object obj, int ms);
132 public static bool Wait (object obj)
134 return Wait (obj, Timeout.Infinite);
137 public static bool Wait (object obj, int millisecondsTimeout)
140 throw new ArgumentNullException ("obj");
142 if (millisecondsTimeout < Timeout.Infinite)
143 throw new ArgumentOutOfRangeException ("millisecondsTimeout", "timeout out of range");
145 if (!Monitor_test_synchronised (obj))
146 throw new SynchronizationLockException ("Object is not synchronized");
148 return Monitor_wait (obj, millisecondsTimeout);
151 public static bool Wait (object obj, TimeSpan timeout)
153 long ms = (long) timeout.TotalMilliseconds;
154 if (ms < Timeout.Infinite || ms > Int32.MaxValue)
155 throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
157 return Wait (obj, (int) ms);
160 public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) {
164 throw new NotSupportedException ("exitContext == true is not supported");
166 SynchronizationAttribute.ExitContext ();
169 return Wait (obj, millisecondsTimeout);
172 if (exitContext) SynchronizationAttribute.EnterContext ();
176 public static bool Wait(object obj, TimeSpan timeout, bool exitContext) {
180 throw new NotSupportedException ("exitContext == true is not supported");
182 SynchronizationAttribute.ExitContext ();
185 return Wait (obj, timeout);
188 if (exitContext) SynchronizationAttribute.EnterContext ();
192 [MethodImplAttribute(MethodImplOptions.InternalCall)]
193 extern static void try_enter_with_atomic_var (object obj, int millisecondsTimeout, ref bool lockTaken);
195 [MethodImplAttribute(MethodImplOptions.InternalCall)]
196 extern static void enter_with_atomic_var (object obj, ref bool lockTaken);
198 // Can't make this an icall since it has the same name as the other Enter method
199 [MethodImpl(MethodImplOptions.AggressiveInlining)]
200 public static void Enter (object obj, ref bool lockTaken)
202 enter_with_atomic_var (obj, ref lockTaken);
205 public static void TryEnter (object obj, ref bool lockTaken)
207 TryEnter (obj, 0, ref lockTaken);
210 public static void TryEnter (object obj, TimeSpan timeout, ref bool lockTaken)
212 long ms = (long) timeout.TotalMilliseconds;
213 if (ms < Timeout.Infinite || ms > Int32.MaxValue)
214 throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
215 TryEnter (obj, (int)ms, ref lockTaken);
218 public static void TryEnter (object obj, int millisecondsTimeout, ref bool lockTaken)
221 throw new ArgumentNullException ("obj");
223 throw new ArgumentException ("lockTaken");
225 if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
226 throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");
228 try_enter_with_atomic_var (obj, millisecondsTimeout, ref lockTaken);
232 [MethodImplAttribute(MethodImplOptions.InternalCall)]
233 extern static bool Monitor_test_owner (object obj);
236 static bool IsEntered (object obj)
238 return Monitor_test_owner(obj);