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
- FontStretchConverter.cs
- ScrollableControl.cs
- VariableAction.cs
- FontStretch.cs
- XmlnsCompatibleWithAttribute.cs
- RoleGroupCollection.cs
- PermissionRequestEvidence.cs
- Point.cs
- StorageInfo.cs
- Bold.cs
- ECDiffieHellman.cs
- TraceListeners.cs
- TableProvider.cs
- XmlLangPropertyAttribute.cs
- UIElement3D.cs
- CodeCatchClauseCollection.cs
- ProjectionPruner.cs
- CommunicationException.cs
- RowUpdatedEventArgs.cs
- DataSourceGroupCollection.cs
- cookiecollection.cs
- MenuAutomationPeer.cs
- SmtpException.cs
- IndicShape.cs
- MaskedTextBoxDesignerActionList.cs
- FormattedText.cs
- LayoutTableCell.cs
- Win32Exception.cs
- CommonDialog.cs
- BrowserCapabilitiesFactoryBase.cs
- SafeProcessHandle.cs
- RSACryptoServiceProvider.cs
- AssemblyAttributesGoHere.cs
- WsdlContractConversionContext.cs
- SchemaSetCompiler.cs
- QueryOperatorEnumerator.cs
- DiscoveryUtility.cs
- HtmlForm.cs
- SamlAdvice.cs
- LinqDataSourceView.cs
- dbenumerator.cs
- AssemblyAttributes.cs
- ClientSettings.cs
- WebPartEditorApplyVerb.cs
- SafeIUnknown.cs
- ProjectionCamera.cs
- RoleGroup.cs
- ConfigDefinitionUpdates.cs
- complextypematerializer.cs
- Size3D.cs
- DocumentViewerAutomationPeer.cs
- SQLBinaryStorage.cs
- ScrollEvent.cs
- ResourcePart.cs
- GPRECTF.cs
- CheckBoxStandardAdapter.cs
- GeometryHitTestResult.cs
- EventListener.cs
- MSHTMLHostUtil.cs
- PartitionResolver.cs
- TypeNameConverter.cs
- HttpCookie.cs
- StylusButton.cs
- NotifyInputEventArgs.cs
- ArgumentNullException.cs
- IndexOutOfRangeException.cs
- SqlConnectionStringBuilder.cs
- DiscoveryDocumentSerializer.cs
- XComponentModel.cs
- ProfileManager.cs
- XsltArgumentList.cs
- dbdatarecord.cs
- MsmqOutputChannel.cs
- StrongNamePublicKeyBlob.cs
- ReadOnlyAttribute.cs
- ParallelTimeline.cs
- WebPartsPersonalization.cs
- DataTableMapping.cs
- XamlStyleSerializer.cs
- ConsoleCancelEventArgs.cs
- CatalogZoneBase.cs
- ConfigXmlComment.cs
- WebPartUtil.cs
- SkewTransform.cs
- OdbcException.cs
- DesignTimeData.cs
- ClientSettingsSection.cs
- DrawTreeNodeEventArgs.cs
- ReferenceConverter.cs
- ColumnCollection.cs
- Crc32Helper.cs
- ArrayTypeMismatchException.cs
- Metadata.cs
- OneWayChannelListener.cs
- UnsafeNativeMethods.cs
- DiagnosticsConfigurationHandler.cs
- DrawingAttributes.cs
- ControlAdapter.cs
- HttpModule.cs
- ReferencedAssembly.cs