Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / LifetimeManager.cs / 1 / LifetimeManager.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Threading; enum LifetimeState { Opened, Closing, Closed } internal class LifetimeManager { #if DEBUG_EXPENSIVE StackTrace closeStack; #endif bool aborted; int busyCount; ICommunicationWaiter busyWaiter; int busyWaiterCount; object mutex; LifetimeState state; public LifetimeManager(object mutex) { this.mutex = mutex; this.state = LifetimeState.Opened; } public int BusyCount { get { return this.busyCount; } } protected LifetimeState State { get { return this.state; } } protected object ThisLock { get { return this.mutex; } } public void Abort() { lock (this.ThisLock) { if (this.State == LifetimeState.Closed || this.aborted) return; #if DEBUG_EXPENSIVE if (closeStack == null) closeStack = new StackTrace(); #endif this.aborted = true; this.state = LifetimeState.Closing; } this.OnAbort(); this.state = LifetimeState.Closed; } void ThrowIfNotOpened() { if (!this.aborted && this.state != LifetimeState.Opened) { #if DEBUG_EXPENSIVE String originalStack = closeStack.ToString().Replace("\r\n", "\r\n "); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString() + ", Object already closed:\r\n " + originalStack)); #else throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); #endif } } public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) { lock (this.ThisLock) { this.ThrowIfNotOpened(); #if DEBUG_EXPENSIVE if (closeStack == null) closeStack = new StackTrace(); #endif this.state = LifetimeState.Closing; } return this.OnBeginClose(timeout, callback, state); } public void Close(TimeSpan timeout) { lock (this.ThisLock) { this.ThrowIfNotOpened(); #if DEBUG_EXPENSIVE if (closeStack == null) closeStack = new StackTrace(); #endif this.state = LifetimeState.Closing; } this.OnClose(timeout); this.state = LifetimeState.Closed; } CommunicationWaitResult CloseCore(TimeSpan timeout, bool aborting) { ICommunicationWaiter busyWaiter = null; CommunicationWaitResult result = CommunicationWaitResult.Succeeded; lock (this.ThisLock) { if (this.busyCount > 0) { if (this.busyWaiter != null) { if (!aborting && this.aborted) return CommunicationWaitResult.Aborted; busyWaiter = this.busyWaiter; } else { busyWaiter = new SyncCommunicationWaiter(this.ThisLock); this.busyWaiter = busyWaiter; } Interlocked.Increment(ref busyWaiterCount); } } if (busyWaiter != null) { result = busyWaiter.Wait(timeout, aborting); if (Interlocked.Decrement(ref busyWaiterCount) == 0) { busyWaiter.Dispose(); this.busyWaiter = null; } } return result; } protected void DecrementBusyCount() { ICommunicationWaiter busyWaiter = null; bool empty = false; lock (this.ThisLock) { if (this.busyCount <= 0) { DiagnosticUtility.DebugAssert("LifetimeManager.DecrementBusyCount: (this.busyCount > 0)"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if (--this.busyCount == 0) { if (this.busyWaiter != null) { busyWaiter = this.busyWaiter; Interlocked.Increment(ref this.busyWaiterCount); } empty = true; } } if (busyWaiter != null) { busyWaiter.Signal(); if (Interlocked.Decrement(ref this.busyWaiterCount) == 0) { busyWaiter.Dispose(); this.busyWaiter = null; } } if (empty && this.State == LifetimeState.Opened) OnEmpty(); } public void EndClose(IAsyncResult result) { this.OnEndClose(result); this.state = LifetimeState.Closed; } protected virtual void IncrementBusyCount() { lock (this.ThisLock) { DiagnosticUtility.DebugAssert(this.State == LifetimeState.Opened, "LifetimeManager.IncrementBusyCount: (this.State == LifetimeState.Opened)"); this.busyCount++; } } protected virtual void IncrementBusyCountWithoutLock() { DiagnosticUtility.DebugAssert(this.State == LifetimeState.Opened, "LifetimeManager.IncrementBusyCountWithoutLock: (this.State == LifetimeState.Opened)"); this.busyCount++; } protected virtual void OnAbort() { // We have decided not to make this configurable CloseCore(TimeSpan.FromSeconds(1), true); } protected virtual IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { CloseCommunicationAsyncResult closeResult = null; Exception exception = null; lock (this.ThisLock) { if (this.busyCount > 0) { if (this.busyWaiter != null) { DiagnosticUtility.DebugAssert(this.aborted, "LifetimeManager.OnBeginClose: (this.aborted == true)"); exception = new ObjectDisposedException(this.GetType().ToString()); } else { closeResult = new CloseCommunicationAsyncResult(timeout, callback, state, this.ThisLock); DiagnosticUtility.DebugAssert(this.busyWaiter == null, "LifetimeManager.OnBeginClose: (this.busyWaiter == null)"); this.busyWaiter = closeResult; Interlocked.Increment(ref this.busyWaiterCount); } } } if (closeResult != null) return closeResult; else return new CompletedAsyncResult(exception, callback, state); } protected virtual void OnClose(TimeSpan timeout) { switch (CloseCore(timeout, false)) { case CommunicationWaitResult.Expired: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.SFxCloseTimedOut1, timeout))); case CommunicationWaitResult.Aborted: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); } } protected virtual void OnEmpty() { } protected virtual void OnEndClose(IAsyncResult result) { if (result is CloseCommunicationAsyncResult) { CloseCommunicationAsyncResult.End(result); if (Interlocked.Decrement(ref this.busyWaiterCount) == 0) { this.busyWaiter.Dispose(); this.busyWaiter = null; } } else CompletedAsyncResult.End(result); } } internal enum CommunicationWaitResult { Waiting, Succeeded, Expired, Aborted } internal interface ICommunicationWaiter : IDisposable { void Signal(); CommunicationWaitResult Wait(TimeSpan timeout, bool aborting); } internal class CloseCommunicationAsyncResult : AsyncResult, ICommunicationWaiter { object mutex; CommunicationWaitResult result; IOThreadTimer timer; TimeoutHelper timeoutHelper; TimeSpan timeout; public CloseCommunicationAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, object mutex) : base(callback, state) { this.timeout = timeout; this.timeoutHelper = new TimeoutHelper(timeout); this.mutex = mutex; if (timeout < TimeSpan.Zero) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.SFxCloseTimedOut1, timeout))); this.timer = new IOThreadTimer(TimeoutCallback, this, true); this.timer.Set(timeout); } object ThisLock { get { return mutex; } } public void Dispose() { } public static void End(IAsyncResult result) { AsyncResult.End(result); } public void Signal() { lock (this.ThisLock) { if (this.result != CommunicationWaitResult.Waiting) return; this.result = CommunicationWaitResult.Succeeded; } this.timer.Cancel(); this.Complete(false); } void Timeout() { lock (this.ThisLock) { if (this.result != CommunicationWaitResult.Waiting) return; this.result = CommunicationWaitResult.Expired; } this.Complete(false, new TimeoutException(SR.GetString(SR.SFxCloseTimedOut1, this.timeout))); } static void TimeoutCallback(object state) { CloseCommunicationAsyncResult closeResult = (CloseCommunicationAsyncResult)state; closeResult.Timeout(); } public CommunicationWaitResult Wait(TimeSpan timeout, bool aborting) { if (timeout < TimeSpan.Zero) return CommunicationWaitResult.Expired; // Synchronous Wait on AsyncResult should only be called in Abort code-path DiagnosticUtility.DebugAssert(aborting, "CloseCommunicationAsyncResult.Wait: (aborting == true)"); lock (this.ThisLock) { if (this.result != CommunicationWaitResult.Waiting) return this.result; this.result = CommunicationWaitResult.Aborted; } this.timer.Cancel(); TimeoutHelper.WaitOne(this.AsyncWaitHandle, timeout, false); this.Complete(false, new ObjectDisposedException(this.GetType().ToString())); return this.result; } } internal class SyncCommunicationWaiter : ICommunicationWaiter { bool closed; object mutex; CommunicationWaitResult result; ManualResetEvent waitHandle; public SyncCommunicationWaiter(object mutex) { this.mutex = mutex; this.waitHandle = new ManualResetEvent(false); } object ThisLock { get { return this.mutex; } } public void Dispose() { lock (this.ThisLock) { if (this.closed) return; this.closed = true; this.waitHandle.Close(); } } public void Signal() { lock (this.ThisLock) { if (this.closed) return; this.waitHandle.Set(); } } public CommunicationWaitResult Wait(TimeSpan timeout, bool aborting) { if (this.closed) return CommunicationWaitResult.Aborted; if (timeout < TimeSpan.Zero) return CommunicationWaitResult.Expired; if (aborting) this.result = CommunicationWaitResult.Aborted; bool expired = !TimeoutHelper.WaitOne(this.waitHandle, timeout, false); lock (this.ThisLock) { if (this.result == CommunicationWaitResult.Waiting) this.result = (expired ? CommunicationWaitResult.Expired : CommunicationWaitResult.Succeeded); } lock (this.ThisLock) { if (!this.closed) this.waitHandle.Set(); // unblock other waiters if there are any } return this.result; } } } // 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
- sitestring.cs
- CalendarAutoFormat.cs
- RowsCopiedEventArgs.cs
- DecodeHelper.cs
- FileAuthorizationModule.cs
- ReflectionHelper.cs
- InfoCardSymmetricAlgorithm.cs
- SelectedDatesCollection.cs
- Int32Rect.cs
- Array.cs
- CodeExporter.cs
- MailMessageEventArgs.cs
- ClientProxyGenerator.cs
- SystemIPInterfaceProperties.cs
- PriorityItem.cs
- ListDictionaryInternal.cs
- Literal.cs
- AttributeInfo.cs
- ProfileSection.cs
- ItemCollection.cs
- EventData.cs
- TreeViewCancelEvent.cs
- LockedBorderGlyph.cs
- DataGridColumnCollection.cs
- WSTrustDec2005.cs
- WebBrowserBase.cs
- FormatStringEditor.cs
- XmlUtf8RawTextWriter.cs
- DispatcherHookEventArgs.cs
- MetadataItemEmitter.cs
- TableLayoutRowStyleCollection.cs
- DisplayInformation.cs
- ObjectDataSourceChooseMethodsPanel.cs
- CommandExpr.cs
- LookupNode.cs
- WindowsGraphicsCacheManager.cs
- ResourcePool.cs
- SelectionWordBreaker.cs
- XmlElementList.cs
- TaskHelper.cs
- ServiceOperation.cs
- MarshalByRefObject.cs
- StringUtil.cs
- TimeoutTimer.cs
- MorphHelper.cs
- RichTextBox.cs
- WebUtil.cs
- TextEditorMouse.cs
- ElapsedEventArgs.cs
- FrugalMap.cs
- PenContexts.cs
- wgx_render.cs
- XXXInfos.cs
- SqlTypeSystemProvider.cs
- ObjectManager.cs
- OutputCacheProfileCollection.cs
- TreeNodeStyleCollection.cs
- SqlMethods.cs
- ToolboxComponentsCreatingEventArgs.cs
- ContainsRowNumberChecker.cs
- XmlQualifiedNameTest.cs
- CancellationToken.cs
- GridViewColumnHeader.cs
- ObjectStateManager.cs
- NameNode.cs
- Symbol.cs
- BufferedReceiveElement.cs
- TypedTableBase.cs
- HtmlInputText.cs
- MemoryStream.cs
- RuleSetDialog.Designer.cs
- EditableRegion.cs
- ButtonAutomationPeer.cs
- IIS7WorkerRequest.cs
- CustomAttributeFormatException.cs
- CustomErrorsSection.cs
- WebBrowser.cs
- RoleServiceManager.cs
- SqlGenericUtil.cs
- FamilyMapCollection.cs
- VoiceSynthesis.cs
- BindingsCollection.cs
- ApplicationServiceHelper.cs
- AlphaSortedEnumConverter.cs
- LinkedResource.cs
- KeyConstraint.cs
- FixedFindEngine.cs
- ListViewInsertEventArgs.cs
- CompilerTypeWithParams.cs
- MenuItemStyle.cs
- HeaderPanel.cs
- CircleEase.cs
- PointCollection.cs
- _ConnectStream.cs
- HWStack.cs
- GridViewSortEventArgs.cs
- CompareValidator.cs
- COM2ExtendedUITypeEditor.cs
- HandlerWithFactory.cs
- SupportsEventValidationAttribute.cs