Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / xsp / System / Web / Compilation / CompilationLock.cs / 1 / CompilationLock.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
//#define MUTEXINSTRUMENTATION
namespace System.Web.Compilation {
using System;
using System.Threading;
using System.Globalization;
using System.Security.Principal;
using System.Web.Util;
using System.Web.Configuration;
using System.Runtime.InteropServices;
using System.Web.Management;
using System.Runtime.Versioning;
using System.Diagnostics;
using Debug = System.Web.Util.Debug;
internal sealed class CompilationMutex : IDisposable {
private String _name;
private String _comment;
#if MUTEXINSTRUMENTATION
// Used to keep track of the stack when the mutex is obtained
private string _stackTrace;
#endif
// ROTORTODO: replace unmanaged aspnet_isapi mutex with managed implementation
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
private HandleRef _mutexHandle;
// Lock Status is used to drain out all worker threads out of Mutex ownership on
// app domain shutdown: -1 locked for good, 0 unlocked, N locked by a worker thread(s)
private int _lockStatus;
private bool _draining = false;
#endif // !FEATURE_PAL
internal CompilationMutex(String name, String comment) {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
// Attempt to get the mutex string from the registry (VSWhidbey 415795)
string mutexRandomName = (string) Misc.GetAspNetRegValue("CompilationMutexName",
null /*valueName*/, null /*defaultValue*/);
if (mutexRandomName != null) {
// If we were able to use the registry value, use it. Also, we need to prepend "Global\"
// to the mutex name, to make sure it can be shared between a terminal server session
// and IIS (VSWhidbey 307523).
_name += @"Global\" + name + "-" + mutexRandomName;
}
else {
// If we couldn't get the reg value, don't use it, and prepend "Local\" to the mutex
// name to make it local to the session (and hence prevent hijacking)
_name += @"Local\" + name;
}
_comment = comment;
Debug.Trace("Mutex", "Creating Mutex " + MutexDebugName);
_mutexHandle = new HandleRef(this, UnsafeNativeMethods.InstrumentedMutexCreate(_name));
if (_mutexHandle.Handle == IntPtr.Zero) {
Debug.Trace("Mutex", "Failed to create Mutex " + MutexDebugName);
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Create));
}
Debug.Trace("Mutex", "Successfully created Mutex " + MutexDebugName);
#endif // !FEATURE_PAL
}
~CompilationMutex() {
Close();
}
void IDisposable.Dispose() {
Close();
System.GC.SuppressFinalize(this);
}
internal /*public*/ void Close() {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
if (_mutexHandle.Handle != IntPtr.Zero) {
UnsafeNativeMethods.InstrumentedMutexDelete(_mutexHandle);
_mutexHandle = new HandleRef(this, IntPtr.Zero);
}
#endif // !FEATURE_PAL
}
[ResourceExposure(ResourceScope.None)]
internal /*public*/ void WaitOne() {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
if (_mutexHandle.Handle == IntPtr.Zero)
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Null));
// check the lock status
for (;;) {
int lockStatus = _lockStatus;
if (lockStatus == -1 || _draining)
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Drained));
if (Interlocked.CompareExchange(ref _lockStatus, lockStatus+1, lockStatus) == lockStatus)
break; // got the lock
}
Debug.Trace("Mutex", "Waiting for mutex " + MutexDebugName);
if (UnsafeNativeMethods.InstrumentedMutexGetLock(_mutexHandle, -1) == -1) {
// failed to get the lock
Interlocked.Decrement(ref _lockStatus);
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Failed));
}
#if MUTEXINSTRUMENTATION
// Remember the stack trace for debugging purpose
_stackTrace = (new StackTrace()).ToString();
#endif
Debug.Trace("Mutex", "Got mutex " + MutexDebugName);
#endif // !FEATURE_PAL
}
#if UNUSED_CODE
internal bool CheckOrFail() {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
if (_mutexHandle.Handle == IntPtr.Zero)
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Null));
// check the lock status
for (;;) {
int lockStatus = _lockStatus;
if (lockStatus == -1 || _draining)
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Drained));
if (Interlocked.CompareExchange(ref _lockStatus, lockStatus+1, lockStatus) == lockStatus)
break; // got the lock
}
Debug.Trace("Mutex", "Checking on mutex " + MutexDebugName);
if (UnsafeNativeMethods.InstrumentedMutexGetLock(_mutexHandle, 0) == -1) {
// failed to get the lock
Debug.Trace("Mutex", "Didn't get mutex " + MutexDebugName);
Interlocked.Decrement(ref _lockStatus);
return false;
}
Debug.Trace("Mutex", "Got mutex " + MutexDebugName);
return true;
#else
return false;
#endif // !FEATURE_PAL
}
#endif
internal /*public*/ void ReleaseMutex() {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
if (_mutexHandle.Handle == IntPtr.Zero)
throw new InvalidOperationException(SR.GetString(SR.CompilationMutex_Null));
Debug.Trace("Mutex", "Releasing mutex " + MutexDebugName);
#if MUTEXINSTRUMENTATION
// Clear out the stack trace
_stackTrace = null;
#endif
if (UnsafeNativeMethods.InstrumentedMutexReleaseLock(_mutexHandle) != 0)
Interlocked.Decrement(ref _lockStatus);
#endif // !FEATURE_PAL
}
#if UNUSED
internal /*public*/ void DrainMutex() {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
// keep trying to set _lockStatus to -1 if it is 0
Debug.Trace("Mutex", "Starting draining mutex " + MutexDebugName);
_draining = true;
for (;;) {
if (_lockStatus == -1)
break;
if (Interlocked.CompareExchange(ref _lockStatus, -1, 0) == 0)
break; // got it
Thread.Sleep(100);
}
Debug.Trace("Mutex", "Completed drained mutex " + MutexDebugName);
#endif // !FEATURE_PAL
}
internal /*public*/ void SetState(int state) {
#if !FEATURE_PAL // No unmanaged aspnet_isapi mutex in Coriolis
if (_mutexHandle.Handle != IntPtr.Zero)
UnsafeNativeMethods.InstrumentedMutexSetState(_mutexHandle, state);
#endif // FEATURE_PAL
}
#endif
private String MutexDebugName {
get {
#if DBG
return (_comment != null) ? _name + " (" + _comment + ")" : _name;
#else
return _name;
#endif
}
}
}
internal static class CompilationLock {
private static CompilationMutex _mutex;
static CompilationLock() {
// Create the mutex (or just get it if another process created it).
// Make the mutex unique per application
int hashCode = ("CompilationLock" + HttpRuntime.AppDomainAppIdInternal.ToLower(CultureInfo.InvariantCulture)).GetHashCode();
_mutex = new CompilationMutex(
"CL" + hashCode.ToString("x", CultureInfo.InvariantCulture),
"CompilationLock for " + HttpRuntime.AppDomainAppVirtualPath);
}
internal static void GetLock(ref bool gotLock) {
// The idea of this try/finally is to make sure that the statements are always
// executed together (VSWhidbey 319154)
// This code should be using a constrained execution region.
try {
}
finally {
// Always take the BuildManager lock *before* taking the mutex, to avoid possible
// deadlock situations (VSWhidbey 530732)
Monitor.Enter(BuildManager.TheBuildManager);
_mutex.WaitOne();
gotLock = true;
}
}
internal static void ReleaseLock() {
_mutex.ReleaseMutex();
Monitor.Exit(BuildManager.TheBuildManager);
}
#if UNUSED
internal static void DrainMutex() {
_mutex.DrainMutex();
}
internal static void SetMutexState(int state) {
_mutex.SetState(state);
}
#endif
}
}
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TemplatePartAttribute.cs
- Cursors.cs
- DataGridViewAdvancedBorderStyle.cs
- NetTcpBinding.cs
- EventLogPermissionEntryCollection.cs
- DocumentSequence.cs
- NetworkInterface.cs
- XNameTypeConverter.cs
- ToolStripHighContrastRenderer.cs
- IpcChannelHelper.cs
- SqlAliaser.cs
- WebPartMenu.cs
- TabControlCancelEvent.cs
- VariableQuery.cs
- ImplicitInputBrush.cs
- EdmFunctions.cs
- EntityConnection.cs
- DataGridViewColumnCollection.cs
- SecurityDescriptor.cs
- XmlLinkedNode.cs
- SoapCommonClasses.cs
- ZipPackagePart.cs
- BeginGetFileNameFromUserRequest.cs
- FilteredAttributeCollection.cs
- EntityWrapper.cs
- CSharpCodeProvider.cs
- PrintPreviewDialog.cs
- IconBitmapDecoder.cs
- TextCompositionEventArgs.cs
- KeyBinding.cs
- UnsafeNativeMethods.cs
- FixedSOMSemanticBox.cs
- OciEnlistContext.cs
- _NegotiateClient.cs
- PTUtility.cs
- WpfMemberInvoker.cs
- XPathNode.cs
- XmlSerializationWriter.cs
- AddInStore.cs
- CallId.cs
- TextDecorationCollectionConverter.cs
- Point3DCollection.cs
- StringValidatorAttribute.cs
- TableRowsCollectionEditor.cs
- HttpWebRequest.cs
- IssuedSecurityTokenProvider.cs
- ConfigurationProperty.cs
- SyndicationSerializer.cs
- XmlSchema.cs
- Compiler.cs
- DataObjectCopyingEventArgs.cs
- WsdlBuildProvider.cs
- Scalars.cs
- PropertyValueUIItem.cs
- GroupBox.cs
- XmlQueryType.cs
- SchemaReference.cs
- CompositeFontInfo.cs
- Label.cs
- GetWinFXPath.cs
- TraceData.cs
- PropertyGeneratedEventArgs.cs
- RuntimeCompatibilityAttribute.cs
- DoubleCollection.cs
- GeneralTransformGroup.cs
- WebPart.cs
- StringSource.cs
- InputBuffer.cs
- ColorPalette.cs
- Mappings.cs
- GeneralTransform3D.cs
- DefaultValueTypeConverter.cs
- ProgressPage.cs
- ThreadPool.cs
- TextSelection.cs
- EndpointReference.cs
- Environment.cs
- WindowsSolidBrush.cs
- ObjectRef.cs
- FrameDimension.cs
- MULTI_QI.cs
- ReplyChannelBinder.cs
- AutomationInteropProvider.cs
- TextElement.cs
- ContactManager.cs
- GAC.cs
- NativeMethods.cs
- PropertyFilterAttribute.cs
- EventMappingSettings.cs
- RegistrySecurity.cs
- CallSiteOps.cs
- SelectManyQueryOperator.cs
- HostProtectionException.cs
- Animatable.cs
- WebPartMenu.cs
- VisualTreeHelper.cs
- DictionaryManager.cs
- EventSinkActivity.cs
- MetadataItemSerializer.cs
- SwitchAttribute.cs