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 partial 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");
70 [System.Security.SecuritySafeCritical]
71 [ResourceExposure(ResourceScope.None)]
72 [MethodImplAttribute(MethodImplOptions.InternalCall)]
73 private static extern void ReliableEnter(Object obj, ref bool lockTaken);
77 /*=========================================================================
78 ** Release the monitor lock. If one or more threads are waiting to acquire the
79 ** lock, and the current thread has executed as many Exits as
80 ** Enters, one of the threads will be unblocked and allowed to proceed.
82 ** Exceptions: ArgumentNullException if object is null.
83 ** SynchronizationLockException if the current thread does not
85 =========================================================================*/
86 [System.Security.SecuritySafeCritical]
87 [ResourceExposure(ResourceScope.None)]
88 [MethodImplAttribute(MethodImplOptions.InternalCall)]
89 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
90 public static extern void Exit(Object obj);
92 /*=========================================================================
93 ** Similar to Enter, but will never block. That is, if the current thread can
94 ** acquire the monitor lock without blocking, it will do so and TRUE will
95 ** be returned. Otherwise FALSE will be returned.
97 ** Exceptions: ArgumentNullException if object is null.
98 =========================================================================*/
99 public static bool TryEnter(Object obj)
101 bool lockTaken = false;
102 TryEnter(obj, 0, ref lockTaken);
106 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
107 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
108 public static void TryEnter(Object obj, ref bool lockTaken)
111 ThrowLockTakenException();
113 ReliableEnterTimeout(obj, 0, ref lockTaken);
116 /*=========================================================================
117 ** Version of TryEnter that will block, but only up to a timeout period
118 ** expressed in milliseconds. If timeout == Timeout.Infinite the method
119 ** becomes equivalent to Enter.
121 ** Exceptions: ArgumentNullException if object is null.
122 ** ArgumentException if timeout < 0.
123 =========================================================================*/
124 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
125 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
126 public static bool TryEnter(Object obj, int millisecondsTimeout)
128 bool lockTaken = false;
129 TryEnter(obj, millisecondsTimeout, ref lockTaken);
133 private static int MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
135 long tm = (long)timeout.TotalMilliseconds;
136 if (tm < -1 || tm > (long)Int32.MaxValue)
137 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
141 public static bool TryEnter(Object obj, TimeSpan timeout)
143 return TryEnter(obj, MillisecondsTimeoutFromTimeSpan(timeout));
146 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
147 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
148 public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
151 ThrowLockTakenException();
153 ReliableEnterTimeout(obj, millisecondsTimeout, ref lockTaken);
156 public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken)
159 ThrowLockTakenException();
161 ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken);
165 [System.Security.SecuritySafeCritical]
166 [ResourceExposure(ResourceScope.None)]
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken);
171 [System.Security.SecuritySafeCritical]
172 public static bool IsEntered(object obj)
175 throw new ArgumentNullException("obj");
177 return IsEnteredNative(obj);
181 [System.Security.SecurityCritical]
182 [ResourceExposure(ResourceScope.None)]
183 [MethodImplAttribute(MethodImplOptions.InternalCall)]
184 private static extern bool IsEnteredNative(Object obj);
187 /*========================================================================
188 ** Waits for notification from the object (via a Pulse/PulseAll).
189 ** timeout indicates how long to wait before the method returns.
190 ** This method acquires the monitor waithandle for the object
191 ** If this thread holds the monitor lock for the object, it releases it.
192 ** On exit from the method, it obtains the monitor lock back.
193 ** If exitContext is true then the synchronization domain for the context
194 ** (if in a synchronized context) is exited before the wait and reacquired
196 ** Exceptions: ArgumentNullException if object is null.
197 ========================================================================*/
199 [System.Security.SecurityCritical] // auto-generated
200 [ResourceExposure(ResourceScope.None)]
201 [MethodImplAttribute(MethodImplOptions.InternalCall)]
202 private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj);
205 [System.Security.SecuritySafeCritical] // auto-generated
206 public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext)
209 throw (new ArgumentNullException("obj"));
210 return ObjWait(exitContext, millisecondsTimeout, obj);
213 public static bool Wait(Object obj, TimeSpan timeout, bool exitContext)
215 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), exitContext);
218 public static bool Wait(Object obj, int millisecondsTimeout)
220 return Wait(obj, millisecondsTimeout, false);
223 public static bool Wait(Object obj, TimeSpan timeout)
225 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), false);
228 public static bool Wait(Object obj)
230 return Wait(obj, Timeout.Infinite, false);
233 /*========================================================================
234 ** Sends a notification to a single waiting object.
235 * Exceptions: SynchronizationLockException if this method is not called inside
236 * a synchronized block of code.
237 ========================================================================*/
239 [System.Security.SecurityCritical] // auto-generated
240 [ResourceExposure(ResourceScope.None)]
241 [MethodImplAttribute(MethodImplOptions.InternalCall)]
242 private static extern void ObjPulse(Object obj);
245 [System.Security.SecuritySafeCritical] // auto-generated
246 public static void Pulse(Object obj)
250 throw new ArgumentNullException("obj");
252 Contract.EndContractBlock();
256 /*========================================================================
257 ** Sends a notification to all waiting objects.
258 ========================================================================*/
260 [System.Security.SecurityCritical] // auto-generated
261 [ResourceExposure(ResourceScope.None)]
262 [MethodImplAttribute(MethodImplOptions.InternalCall)]
263 private static extern void ObjPulseAll(Object obj);
266 [System.Security.SecuritySafeCritical] // auto-generated
267 public static void PulseAll(Object obj)
271 throw new ArgumentNullException("obj");
273 Contract.EndContractBlock();