Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / RunTime / Lock.cs / 1305376 / Lock.cs
// **************************************************************************** // Copyright (C) Microsoft Corporation. All rights reserved. // // CONTENTS // Value-add wrapper on top of standard CLR monitor // using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Xml; using System.Reflection; using System.Threading; using System.Diagnostics; using System.Transactions; using System.Workflow.Runtime.Hosting; namespace System.Workflow.Runtime { internal static class LockFactory { internal static InstanceLock CreateWorkflowExecutorLock(Guid id) { return new InstanceLock(id, "Workflow Executor Lock: " + id.ToString(), 50, LockPriorityOperator.GreaterThanOrReentrant); } internal static InstanceLock CreateWorkflowSchedulerLock(Guid id) { return new InstanceLock(id, "Workflow Scheduler Lock: " + id.ToString(), 40, LockPriorityOperator.GreaterThan); } internal static InstanceLock CreateWorkflowMessageDeliveryLock(Guid id) { return new InstanceLock(id, "Workflow Message Delivery Lock: " + id.ToString(), 35, LockPriorityOperator.GreaterThanOrReentrant); } } internal enum LockPriorityOperator { GreaterThan, GreaterThanOrReentrant, } internal sealed class InstanceLock { #region Static Data/Methods [ThreadStaticAttribute()] private static Listt_heldLocks = null; [Conditional("DEBUG")] internal static void AssertNoLocksHeld() { #if DEBUG System.Diagnostics.Debug.Assert(HeldLocks.Count == 0, "No locks should be held."); #endif } [Conditional("DEBUG")] internal static void AssertIsLocked(InstanceLock theLock) { #if DEBUG System.Diagnostics.Debug.Assert(HeldLocks.Contains(theLock), "Lock should be held."); #endif } private static List HeldLocks { get { List tLocks = InstanceLock.t_heldLocks; if (tLocks == null) { InstanceLock.t_heldLocks = new List (); tLocks = InstanceLock.t_heldLocks; } return tLocks; } } #endregion Static Data/Methods private Guid m_instanceId; private String m_name; private int m_priority; private LockPriorityOperator m_operator; internal int Priority { get { return this.m_priority; } } internal LockPriorityOperator Operator { get { return this.m_operator; } } internal InstanceLock(Guid id, String name, int priority, LockPriorityOperator lockOperator) { this.m_instanceId = id; this.m_name = name; this.m_priority = priority; this.m_operator = lockOperator; } internal Guid InstanceId { get { return this.m_instanceId; } } internal InstanceLockGuard Enter() { return new InstanceLockGuard(this); } internal bool TryEnter() { InstanceLockGuard.EnforceGuard(this); bool lockHeld = false; bool success = false; try { Monitor.TryEnter(this, ref lockHeld); if (lockHeld) { HeldLocks.Add(this); success = true; } } finally { if (lockHeld && !success) { Monitor.Exit(this); } } return success; } internal void Exit() { try { HeldLocks.Remove(this); } finally { Monitor.Exit(this); } } internal struct InstanceLockGuard : IDisposable { readonly InstanceLock m_lock; internal static void EnforceGuard(InstanceLock theLock) { foreach (InstanceLock heldLock in HeldLocks) { switch (theLock.Operator) { case LockPriorityOperator.GreaterThan: if (heldLock.InstanceId == theLock.InstanceId && heldLock.Priority <= theLock.Priority) throw new InvalidOperationException(ExecutionStringManager.InstanceOperationNotValidinWorkflowThread); break; case LockPriorityOperator.GreaterThanOrReentrant: // the checks here assume that locks have unique priorities if (heldLock.InstanceId == theLock.InstanceId && heldLock.Priority < theLock.Priority) throw new InvalidOperationException(ExecutionStringManager.InstanceOperationNotValidinWorkflowThread); break; default: System.Diagnostics.Debug.Assert(false, "Unrecognized lock operator"); break; } } } internal InstanceLockGuard(InstanceLock theLock) { this.m_lock = theLock; // Note: the following operations are logically atomic, but since the // list we are using is thread local there is no need to take a lock. EnforceGuard(theLock); try { } finally { bool success = false; #pragma warning disable 0618 //@ Monitor.Enter(this.m_lock); #pragma warning restore 0618 try { HeldLocks.Add(this.m_lock); success = true; } finally { if (!success) { Monitor.Exit(this.m_lock); } } } } internal void Pulse() { Monitor.Pulse(this.m_lock); } internal void Wait() { Monitor.Wait(this.m_lock); } public void Dispose() { // Note: the following operations are logically atomic, but since the // list we are using is thread local there is no need to take a lock. try { HeldLocks.Remove(this.m_lock); } finally { Monitor.Exit(this.m_lock); } } } } internal sealed class SchedulerLockGuard : IDisposable { private InstanceLock.InstanceLockGuard lg; private WorkflowExecutor workflowExec; internal SchedulerLockGuard(InstanceLock il, WorkflowExecutor w) { lg = il.Enter(); workflowExec = w; } private static void FireEvents(List eventList, WorkflowExecutor workflowExec) { if (!workflowExec.IsInstanceValid && (workflowExec.WorkflowStatus == WorkflowStatus.Completed || workflowExec.WorkflowStatus == WorkflowStatus.Terminated)) { // The workflow is dead, let the instance have a hard ref to the corpse for support of the query apis. workflowExec.WorkflowInstance.DeadWorkflow = workflowExec; } for (int i = 0; i < eventList.Count; i++) { SchedulerLockGuardInfo eseg = eventList[i]; // eseg.EventInfo is non-null only if the event type is Suspended or Terminated // If the event type is Suspended, then call FireWorkflowSuspended after casting // the event argument to a String. // If the event type is Terminated, then call FireWorkflowTerminated after casting // the event argument to either a String or an Exception. switch (eseg.EventType) { case WorkflowEventInternal.Suspended: workflowExec.FireWorkflowSuspended((String)eseg.EventInfo); break; case WorkflowEventInternal.Terminated: if ((eseg.EventInfo as System.Exception) != null) { workflowExec.FireWorkflowTerminated((Exception)eseg.EventInfo); } else { workflowExec.FireWorkflowTerminated((String)eseg.EventInfo); } break; default: workflowExec.FireWorkflowExecutionEvent(eseg.Sender, eseg.EventType); break; } } } internal static void Exit(InstanceLock il, WorkflowExecutor w) { List eventList = new List (w.EventsToFireList); w.EventsToFireList.Clear(); il.Exit(); FireEvents(eventList, w); } public void Dispose() { List eventList = new List (workflowExec.EventsToFireList); workflowExec.EventsToFireList.Clear(); lg.Dispose(); FireEvents(eventList, workflowExec); } } internal sealed class SchedulerLockGuardInfo { private Object sender; private WorkflowEventInternal eventType; private object eventInfo; internal SchedulerLockGuardInfo(Object _sender, WorkflowEventInternal _eventType) { sender = _sender; eventType = _eventType; eventInfo = null; } internal SchedulerLockGuardInfo(Object _sender, WorkflowEventInternal _eventType, object _eventInfo) : this(_sender, _eventType) { eventInfo = _eventInfo; } internal Object Sender { get { return sender; } } internal WorkflowEventInternal EventType { get { return eventType; } } internal Object EventInfo { get { return eventInfo; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. // **************************************************************************** // Copyright (C) Microsoft Corporation. All rights reserved. // // CONTENTS // Value-add wrapper on top of standard CLR monitor // using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Xml; using System.Reflection; using System.Threading; using System.Diagnostics; using System.Transactions; using System.Workflow.Runtime.Hosting; namespace System.Workflow.Runtime { internal static class LockFactory { internal static InstanceLock CreateWorkflowExecutorLock(Guid id) { return new InstanceLock(id, "Workflow Executor Lock: " + id.ToString(), 50, LockPriorityOperator.GreaterThanOrReentrant); } internal static InstanceLock CreateWorkflowSchedulerLock(Guid id) { return new InstanceLock(id, "Workflow Scheduler Lock: " + id.ToString(), 40, LockPriorityOperator.GreaterThan); } internal static InstanceLock CreateWorkflowMessageDeliveryLock(Guid id) { return new InstanceLock(id, "Workflow Message Delivery Lock: " + id.ToString(), 35, LockPriorityOperator.GreaterThanOrReentrant); } } internal enum LockPriorityOperator { GreaterThan, GreaterThanOrReentrant, } internal sealed class InstanceLock { #region Static Data/Methods [ThreadStaticAttribute()] private static List t_heldLocks = null; [Conditional("DEBUG")] internal static void AssertNoLocksHeld() { #if DEBUG System.Diagnostics.Debug.Assert(HeldLocks.Count == 0, "No locks should be held."); #endif } [Conditional("DEBUG")] internal static void AssertIsLocked(InstanceLock theLock) { #if DEBUG System.Diagnostics.Debug.Assert(HeldLocks.Contains(theLock), "Lock should be held."); #endif } private static List HeldLocks { get { List tLocks = InstanceLock.t_heldLocks; if (tLocks == null) { InstanceLock.t_heldLocks = new List (); tLocks = InstanceLock.t_heldLocks; } return tLocks; } } #endregion Static Data/Methods private Guid m_instanceId; private String m_name; private int m_priority; private LockPriorityOperator m_operator; internal int Priority { get { return this.m_priority; } } internal LockPriorityOperator Operator { get { return this.m_operator; } } internal InstanceLock(Guid id, String name, int priority, LockPriorityOperator lockOperator) { this.m_instanceId = id; this.m_name = name; this.m_priority = priority; this.m_operator = lockOperator; } internal Guid InstanceId { get { return this.m_instanceId; } } internal InstanceLockGuard Enter() { return new InstanceLockGuard(this); } internal bool TryEnter() { InstanceLockGuard.EnforceGuard(this); bool lockHeld = false; bool success = false; try { Monitor.TryEnter(this, ref lockHeld); if (lockHeld) { HeldLocks.Add(this); success = true; } } finally { if (lockHeld && !success) { Monitor.Exit(this); } } return success; } internal void Exit() { try { HeldLocks.Remove(this); } finally { Monitor.Exit(this); } } internal struct InstanceLockGuard : IDisposable { readonly InstanceLock m_lock; internal static void EnforceGuard(InstanceLock theLock) { foreach (InstanceLock heldLock in HeldLocks) { switch (theLock.Operator) { case LockPriorityOperator.GreaterThan: if (heldLock.InstanceId == theLock.InstanceId && heldLock.Priority <= theLock.Priority) throw new InvalidOperationException(ExecutionStringManager.InstanceOperationNotValidinWorkflowThread); break; case LockPriorityOperator.GreaterThanOrReentrant: // the checks here assume that locks have unique priorities if (heldLock.InstanceId == theLock.InstanceId && heldLock.Priority < theLock.Priority) throw new InvalidOperationException(ExecutionStringManager.InstanceOperationNotValidinWorkflowThread); break; default: System.Diagnostics.Debug.Assert(false, "Unrecognized lock operator"); break; } } } internal InstanceLockGuard(InstanceLock theLock) { this.m_lock = theLock; // Note: the following operations are logically atomic, but since the // list we are using is thread local there is no need to take a lock. EnforceGuard(theLock); try { } finally { bool success = false; #pragma warning disable 0618 //@ Monitor.Enter(this.m_lock); #pragma warning restore 0618 try { HeldLocks.Add(this.m_lock); success = true; } finally { if (!success) { Monitor.Exit(this.m_lock); } } } } internal void Pulse() { Monitor.Pulse(this.m_lock); } internal void Wait() { Monitor.Wait(this.m_lock); } public void Dispose() { // Note: the following operations are logically atomic, but since the // list we are using is thread local there is no need to take a lock. try { HeldLocks.Remove(this.m_lock); } finally { Monitor.Exit(this.m_lock); } } } } internal sealed class SchedulerLockGuard : IDisposable { private InstanceLock.InstanceLockGuard lg; private WorkflowExecutor workflowExec; internal SchedulerLockGuard(InstanceLock il, WorkflowExecutor w) { lg = il.Enter(); workflowExec = w; } private static void FireEvents(List eventList, WorkflowExecutor workflowExec) { if (!workflowExec.IsInstanceValid && (workflowExec.WorkflowStatus == WorkflowStatus.Completed || workflowExec.WorkflowStatus == WorkflowStatus.Terminated)) { // The workflow is dead, let the instance have a hard ref to the corpse for support of the query apis. workflowExec.WorkflowInstance.DeadWorkflow = workflowExec; } for (int i = 0; i < eventList.Count; i++) { SchedulerLockGuardInfo eseg = eventList[i]; // eseg.EventInfo is non-null only if the event type is Suspended or Terminated // If the event type is Suspended, then call FireWorkflowSuspended after casting // the event argument to a String. // If the event type is Terminated, then call FireWorkflowTerminated after casting // the event argument to either a String or an Exception. switch (eseg.EventType) { case WorkflowEventInternal.Suspended: workflowExec.FireWorkflowSuspended((String)eseg.EventInfo); break; case WorkflowEventInternal.Terminated: if ((eseg.EventInfo as System.Exception) != null) { workflowExec.FireWorkflowTerminated((Exception)eseg.EventInfo); } else { workflowExec.FireWorkflowTerminated((String)eseg.EventInfo); } break; default: workflowExec.FireWorkflowExecutionEvent(eseg.Sender, eseg.EventType); break; } } } internal static void Exit(InstanceLock il, WorkflowExecutor w) { List eventList = new List (w.EventsToFireList); w.EventsToFireList.Clear(); il.Exit(); FireEvents(eventList, w); } public void Dispose() { List eventList = new List (workflowExec.EventsToFireList); workflowExec.EventsToFireList.Clear(); lg.Dispose(); FireEvents(eventList, workflowExec); } } internal sealed class SchedulerLockGuardInfo { private Object sender; private WorkflowEventInternal eventType; private object eventInfo; internal SchedulerLockGuardInfo(Object _sender, WorkflowEventInternal _eventType) { sender = _sender; eventType = _eventType; eventInfo = null; } internal SchedulerLockGuardInfo(Object _sender, WorkflowEventInternal _eventType, object _eventInfo) : this(_sender, _eventType) { eventInfo = _eventInfo; } internal Object Sender { get { return sender; } } internal WorkflowEventInternal EventType { get { return eventType; } } internal Object EventInfo { get { return eventInfo; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XamlSerializerUtil.cs
- BevelBitmapEffect.cs
- XmlTypeMapping.cs
- CodeTypeMemberCollection.cs
- XmlSchemaSimpleTypeUnion.cs
- ApplicationServicesHostFactory.cs
- XmlRawWriter.cs
- CodeDomSerializerException.cs
- webeventbuffer.cs
- WpfGeneratedKnownTypes.cs
- IisHelper.cs
- SymLanguageVendor.cs
- PropertyRef.cs
- ValueQuery.cs
- FontStyle.cs
- HyperLinkField.cs
- DesignBindingConverter.cs
- Operand.cs
- EventNotify.cs
- MatrixTransform.cs
- OutputScope.cs
- BrowsableAttribute.cs
- FileChangesMonitor.cs
- WindowAutomationPeer.cs
- ConnectionConsumerAttribute.cs
- ByeOperationAsyncResult.cs
- ProviderSettingsCollection.cs
- Package.cs
- CatalogPart.cs
- AccessedThroughPropertyAttribute.cs
- Query.cs
- SrgsRuleRef.cs
- RepeaterItemCollection.cs
- XhtmlBasicCommandAdapter.cs
- OutOfProcStateClientManager.cs
- webeventbuffer.cs
- CheckBoxRenderer.cs
- FileDataSourceCache.cs
- EnumMember.cs
- UriTemplateHelpers.cs
- TimelineCollection.cs
- RpcResponse.cs
- DataRowView.cs
- Activator.cs
- MembershipPasswordException.cs
- ScriptHandlerFactory.cs
- FontUnit.cs
- CodeNamespace.cs
- IPGlobalProperties.cs
- Boolean.cs
- GroupBoxRenderer.cs
- TransformDescriptor.cs
- HealthMonitoringSection.cs
- GcSettings.cs
- FontWeight.cs
- OdbcPermission.cs
- CommonXSendMessage.cs
- Compiler.cs
- Condition.cs
- ExtensibleClassFactory.cs
- FieldToken.cs
- EventItfInfo.cs
- WmfPlaceableFileHeader.cs
- Brush.cs
- GenericTransactionFlowAttribute.cs
- ParallelTimeline.cs
- ScriptingSectionGroup.cs
- UIElementHelper.cs
- _RequestCacheProtocol.cs
- NamedPipeTransportElement.cs
- SafeFileMapViewHandle.cs
- DbDataAdapter.cs
- MergablePropertyAttribute.cs
- ReachVisualSerializer.cs
- SafeTokenHandle.cs
- XmlAttribute.cs
- MouseCaptureWithinProperty.cs
- SafePointer.cs
- RowToFieldTransformer.cs
- PrivateFontCollection.cs
- BooleanFacetDescriptionElement.cs
- PrePostDescendentsWalker.cs
- IdleTimeoutMonitor.cs
- DoubleStorage.cs
- SafeArrayTypeMismatchException.cs
- SimpleApplicationHost.cs
- HMACSHA512.cs
- EntityConnectionStringBuilder.cs
- SoundPlayer.cs
- PanelStyle.cs
- InvalidFilterCriteriaException.cs
- BaseCodeDomTreeGenerator.cs
- ColorAnimationBase.cs
- DocumentPageView.cs
- SchemaCollectionCompiler.cs
- QueryHandler.cs
- StatusBarDrawItemEvent.cs
- KeyedPriorityQueue.cs
- ClockGroup.cs
- SettingsBase.cs