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
- EntitySqlQueryBuilder.cs
- BitmapImage.cs
- CodeNamespaceImportCollection.cs
- TextSegment.cs
- BuildResult.cs
- DesignerActionUI.cs
- TextWriterTraceListener.cs
- MappingSource.cs
- CompatibleComparer.cs
- KeysConverter.cs
- ExceptionRoutedEventArgs.cs
- BitSet.cs
- FolderLevelBuildProviderCollection.cs
- DataGridCommandEventArgs.cs
- PackageRelationshipSelector.cs
- Emitter.cs
- Calendar.cs
- WebPartPersonalization.cs
- ServiceReference.cs
- List.cs
- UnknownWrapper.cs
- Peer.cs
- GetBrowserTokenRequest.cs
- BindingsCollection.cs
- UnmanagedMarshal.cs
- AvTrace.cs
- DataSetViewSchema.cs
- SignatureDescription.cs
- EdmValidator.cs
- _ListenerResponseStream.cs
- MetadataProperty.cs
- DecimalAverageAggregationOperator.cs
- SqlUDTStorage.cs
- Merger.cs
- WebPartMovingEventArgs.cs
- Enum.cs
- ParenExpr.cs
- MissingMemberException.cs
- basemetadatamappingvisitor.cs
- Cloud.cs
- EventSetter.cs
- SemanticTag.cs
- CodeSnippetTypeMember.cs
- EncryptedHeader.cs
- TypeElementCollection.cs
- SortKey.cs
- ResXDataNode.cs
- ProfileModule.cs
- VariableQuery.cs
- RedistVersionInfo.cs
- OdbcConnectionStringbuilder.cs
- AudioException.cs
- HttpClientCertificate.cs
- LoadRetryConstantStrategy.cs
- FontFamilyConverter.cs
- FaultContext.cs
- ByteAnimationBase.cs
- TimeEnumHelper.cs
- XmlDocumentFragment.cs
- SingleSelectRootGridEntry.cs
- Floater.cs
- SqlReorderer.cs
- SelectorItemAutomationPeer.cs
- PropertyKey.cs
- RepeaterCommandEventArgs.cs
- FontDifferentiator.cs
- X509UI.cs
- DatePickerTextBox.cs
- HyperLinkField.cs
- VisualStyleInformation.cs
- PrimitiveDataContract.cs
- DataGridViewCellStyle.cs
- QueryOptionExpression.cs
- ListContractAdapter.cs
- BitmapEffect.cs
- XmlNode.cs
- DataGridCellEditEndingEventArgs.cs
- SchemaImporterExtensionElementCollection.cs
- FrameworkContentElement.cs
- HostProtectionPermission.cs
- MenuItemBinding.cs
- ValueUtilsSmi.cs
- NavigationWindow.cs
- CompoundFileReference.cs
- NumericPagerField.cs
- SmtpMail.cs
- WebPartConnectionsCancelVerb.cs
- TemplateXamlParser.cs
- cookiecontainer.cs
- ServicePointManagerElement.cs
- DashStyles.cs
- RootProfilePropertySettingsCollection.cs
- TriState.cs
- Vector3DAnimation.cs
- Range.cs
- AuthorizationRule.cs
- FieldNameLookup.cs
- InvalidWMPVersionException.cs
- Nullable.cs
- ImmutableObjectAttribute.cs