3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // <OWNER>[....]</OWNER>
8 /*=============================================================================
13 ** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
17 =============================================================================*/
20 namespace System.Threading {
23 using System.Security.Permissions;
25 using System.Runtime.Remoting;
26 using System.Threading;
27 using System.Runtime.CompilerServices;
28 using System.Runtime.ConstrainedExecution;
29 using System.Runtime.Versioning;
30 using System.Diagnostics.Contracts;
32 [HostProtection(Synchronization=true, ExternalThreading=true)]
33 [System.Runtime.InteropServices.ComVisible(true)]
34 public static class Monitor
36 /*=========================================================================
37 ** Obtain the monitor lock of obj. Will block if another thread holds the lock
38 ** Will not block if the current thread holds the lock,
39 ** however the caller must ensure that the same number of Exit
40 ** calls are made as there were Enter calls.
42 ** Exceptions: ArgumentNullException if object is null.
43 =========================================================================*/
44 [System.Security.SecuritySafeCritical]
45 [ResourceExposure(ResourceScope.None)]
46 [MethodImplAttribute(MethodImplOptions.InternalCall)]
47 public static extern void Enter(Object obj);
50 // Use a ref bool instead of out to ensure that unverifiable code must
51 // initialize this value to something. If we used out, the value
52 // could be uninitialized if we threw an exception in our prolog.
53 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
54 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
55 public static void Enter(Object obj, ref bool lockTaken)
58 ThrowLockTakenException();
60 ReliableEnter(obj, ref lockTaken);
61 Contract.Assert(lockTaken);
64 private static void ThrowLockTakenException()
66 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeFalse"), "lockTaken");
69 [System.Security.SecuritySafeCritical]
70 [ResourceExposure(ResourceScope.None)]
71 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72 private static extern void ReliableEnter(Object obj, ref bool lockTaken);
76 /*=========================================================================
77 ** Release the monitor lock. If one or more threads are waiting to acquire the
78 ** lock, and the current thread has executed as many Exits as
79 ** Enters, one of the threads will be unblocked and allowed to proceed.
81 ** Exceptions: ArgumentNullException if object is null.
82 ** SynchronizationLockException if the current thread does not
84 =========================================================================*/
85 [System.Security.SecuritySafeCritical]
86 [ResourceExposure(ResourceScope.None)]
87 [MethodImplAttribute(MethodImplOptions.InternalCall)]
88 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
89 public static extern void Exit(Object obj);
91 /*=========================================================================
92 ** Similar to Enter, but will never block. That is, if the current thread can
93 ** acquire the monitor lock without blocking, it will do so and TRUE will
94 ** be returned. Otherwise FALSE will be returned.
96 ** Exceptions: ArgumentNullException if object is null.
97 =========================================================================*/
98 public static bool TryEnter(Object obj)
100 bool lockTaken = false;
101 TryEnter(obj, 0, ref lockTaken);
105 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
106 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
107 public static void TryEnter(Object obj, ref bool lockTaken)
110 ThrowLockTakenException();
112 ReliableEnterTimeout(obj, 0, ref lockTaken);
115 /*=========================================================================
116 ** Version of TryEnter that will block, but only up to a timeout period
117 ** expressed in milliseconds. If timeout == Timeout.Infinite the method
118 ** becomes equivalent to Enter.
120 ** Exceptions: ArgumentNullException if object is null.
121 ** ArgumentException if timeout < 0.
122 =========================================================================*/
123 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
124 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
125 public static bool TryEnter(Object obj, int millisecondsTimeout)
127 bool lockTaken = false;
128 TryEnter(obj, millisecondsTimeout, ref lockTaken);
132 private static int MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
134 long tm = (long)timeout.TotalMilliseconds;
135 if (tm < -1 || tm > (long)Int32.MaxValue)
136 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
140 public static bool TryEnter(Object obj, TimeSpan timeout)
142 return TryEnter(obj, MillisecondsTimeoutFromTimeSpan(timeout));
145 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
146 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
147 public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
150 ThrowLockTakenException();
152 ReliableEnterTimeout(obj, millisecondsTimeout, ref lockTaken);
155 public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken)
158 ThrowLockTakenException();
160 ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken);
163 [System.Security.SecuritySafeCritical]
164 [ResourceExposure(ResourceScope.None)]
165 [MethodImplAttribute(MethodImplOptions.InternalCall)]
166 private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken);
168 [System.Security.SecuritySafeCritical]
169 public static bool IsEntered(object obj)
172 throw new ArgumentNullException("obj");
174 return IsEnteredNative(obj);
177 [System.Security.SecurityCritical]
178 [ResourceExposure(ResourceScope.None)]
179 [MethodImplAttribute(MethodImplOptions.InternalCall)]
180 private static extern bool IsEnteredNative(Object obj);
182 /*========================================================================
183 ** Waits for notification from the object (via a Pulse/PulseAll).
184 ** timeout indicates how long to wait before the method returns.
185 ** This method acquires the monitor waithandle for the object
186 ** If this thread holds the monitor lock for the object, it releases it.
187 ** On exit from the method, it obtains the monitor lock back.
188 ** If exitContext is true then the synchronization domain for the context
189 ** (if in a synchronized context) is exited before the wait and reacquired
191 ** Exceptions: ArgumentNullException if object is null.
192 ========================================================================*/
193 [System.Security.SecurityCritical] // auto-generated
194 [ResourceExposure(ResourceScope.None)]
195 [MethodImplAttribute(MethodImplOptions.InternalCall)]
196 private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj);
198 [System.Security.SecuritySafeCritical] // auto-generated
199 public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext)
202 throw (new ArgumentNullException("obj"));
203 return ObjWait(exitContext, millisecondsTimeout, obj);
206 public static bool Wait(Object obj, TimeSpan timeout, bool exitContext)
208 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), exitContext);
211 public static bool Wait(Object obj, int millisecondsTimeout)
213 return Wait(obj, millisecondsTimeout, false);
216 public static bool Wait(Object obj, TimeSpan timeout)
218 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), false);
221 public static bool Wait(Object obj)
223 return Wait(obj, Timeout.Infinite, false);
226 /*========================================================================
227 ** Sends a notification to a single waiting object.
228 * Exceptions: SynchronizationLockException if this method is not called inside
229 * a synchronized block of code.
230 ========================================================================*/
231 [System.Security.SecurityCritical] // auto-generated
232 [ResourceExposure(ResourceScope.None)]
233 [MethodImplAttribute(MethodImplOptions.InternalCall)]
234 private static extern void ObjPulse(Object obj);
236 [System.Security.SecuritySafeCritical] // auto-generated
237 public static void Pulse(Object obj)
241 throw new ArgumentNullException("obj");
243 Contract.EndContractBlock();
247 /*========================================================================
248 ** Sends a notification to all waiting objects.
249 ========================================================================*/
250 [System.Security.SecurityCritical] // auto-generated
251 [ResourceExposure(ResourceScope.None)]
252 [MethodImplAttribute(MethodImplOptions.InternalCall)]
253 private static extern void ObjPulseAll(Object obj);
255 [System.Security.SecuritySafeCritical] // auto-generated
256 public static void PulseAll(Object obj)
260 throw new ArgumentNullException("obj");
262 Contract.EndContractBlock();