Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ServiceChannelManager.cs / 1 / ServiceChannelManager.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel { using System.Collections.Generic; using System.Diagnostics; using System.ServiceModel.Channels; using System.Threading; internal delegate void InstanceContextEmptyCallback(InstanceContext instanceContext); internal class ServiceChannelManager : LifetimeManager { int activityCount; ICommunicationWaiter activityWaiter; int activityWaiterCount; InstanceContextEmptyCallback emptyCallback; IChannel firstIncomingChannel; ChannelCollection incomingChannels; ChannelCollection outgoingChannels; InstanceContext instanceContext; public ServiceChannelManager(InstanceContext instanceContext) : this(instanceContext, null) { } public ServiceChannelManager(InstanceContext instanceContext, InstanceContextEmptyCallback emptyCallback) : base(instanceContext.ThisLock) { this.instanceContext = instanceContext; this.emptyCallback = emptyCallback; } public int ActivityCount { get { return this.activityCount; } } public ICollectionIncomingChannels { get { this.EnsureIncomingChannelCollection(); return (ICollection )this.incomingChannels; } } public ICollection OutgoingChannels { get { if (this.outgoingChannels == null) { lock (this.ThisLock) { if (this.outgoingChannels == null) this.outgoingChannels = new ChannelCollection(this, this.ThisLock); } } return this.outgoingChannels; } } public bool IsBusy { get { if (this.ActivityCount > 0) return true; if (base.BusyCount > 0) return true; ICollection outgoing = this.outgoingChannels; if ((outgoing != null) && (outgoing.Count > 0)) return true; return false; } } public void AddIncomingChannel(IChannel channel) { bool added = false; lock (this.ThisLock) { if (this.State == LifetimeState.Opened) { if (this.firstIncomingChannel == null) { if (this.incomingChannels == null) { this.firstIncomingChannel = channel; this.ChannelAdded(channel); } else { if (this.incomingChannels.Contains(channel)) return; this.incomingChannels.Add(channel); } } else { this.EnsureIncomingChannelCollection(); if (this.incomingChannels.Contains(channel)) return; this.incomingChannels.Add(channel); } added = true; } } if (!added) { channel.Abort(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); } } public IAsyncResult BeginCloseInput(TimeSpan timeout, AsyncCallback callback, object state) { CloseCommunicationAsyncResult closeResult = null; lock (this.ThisLock) { if (this.activityCount > 0) { closeResult = new CloseCommunicationAsyncResult(timeout, callback, state, this.ThisLock); if (!(this.activityWaiter == null)) { DiagnosticUtility.DebugAssert("ServiceChannelManager.BeginCloseInput: (this.activityWaiter == null)"); } this.activityWaiter = closeResult; Interlocked.Increment(ref this.activityWaiterCount); } } if (closeResult != null) return closeResult; else return new CompletedAsyncResult(callback, state); } void ChannelAdded(IChannel channel) { base.IncrementBusyCount(); channel.Closed += this.OnChannelClosed; } void ChannelRemoved(IChannel channel) { channel.Closed -= this.OnChannelClosed; base.DecrementBusyCount(); } public void CloseInput(TimeSpan timeout) { SyncCommunicationWaiter activityWaiter = null; lock (this.ThisLock) { if (this.activityCount > 0) { activityWaiter = new SyncCommunicationWaiter(this.ThisLock); if (!(this.activityWaiter == null)) { DiagnosticUtility.DebugAssert("ServiceChannelManager.CloseInput: (this.activityWaiter == null)"); } this.activityWaiter = activityWaiter; Interlocked.Increment(ref this.activityWaiterCount); } } if (activityWaiter != null) { CommunicationWaitResult result = activityWaiter.Wait(timeout, false); if (Interlocked.Decrement(ref this.activityWaiterCount) == 0) { activityWaiter.Dispose(); this.activityWaiter = null; } switch (result) { case CommunicationWaitResult.Expired: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.SfxCloseTimedOutWaitingForDispatchToComplete))); case CommunicationWaitResult.Aborted: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); } } } public void DecrementActivityCount() { ICommunicationWaiter activityWaiter = null; bool empty = false; lock (this.ThisLock) { if (!(this.activityCount > 0)) { DiagnosticUtility.DebugAssert("ServiceChannelManager.DecrementActivityCount: (this.activityCount > 0)"); } if (--this.activityCount == 0) { if (this.activityWaiter != null) { activityWaiter = this.activityWaiter; Interlocked.Increment(ref this.activityWaiterCount); } if (this.BusyCount == 0) empty = true; } } if (activityWaiter != null) { activityWaiter.Signal(); if (Interlocked.Decrement(ref this.activityWaiterCount) == 0) { activityWaiter.Dispose(); this.activityWaiter = null; } } if (empty && this.State == LifetimeState.Opened) OnEmpty(); } public void EndCloseInput(IAsyncResult result) { if (result is CloseCommunicationAsyncResult) { CloseCommunicationAsyncResult.End(result); if (Interlocked.Decrement(ref this.activityWaiterCount) == 0) { this.activityWaiter.Dispose(); this.activityWaiter = null; } } else CompletedAsyncResult.End(result); } void EnsureIncomingChannelCollection() { lock (this.ThisLock) { if (this.incomingChannels == null) { this.incomingChannels = new ChannelCollection(this, this.ThisLock); if (this.firstIncomingChannel != null) { this.incomingChannels.Add(this.firstIncomingChannel); this.ChannelRemoved(this.firstIncomingChannel); // Adding to collection called ChannelAdded, so call ChannelRemoved to balance this.firstIncomingChannel = null; } } } } public void IncrementActivityCount() { lock (this.ThisLock) { if (this.State == LifetimeState.Closed) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); this.activityCount++; } } protected override void IncrementBusyCount() { base.IncrementBusyCount(); } protected override void OnAbort() { IChannel[] channels = this.SnapshotChannels(); for (int index = 0; index < channels.Length; index++) channels[index].Abort(); ICommunicationWaiter activityWaiter = null; lock (this.ThisLock) { if (this.activityWaiter != null) { activityWaiter = this.activityWaiter; Interlocked.Increment(ref this.activityWaiterCount); } } if (activityWaiter != null) { activityWaiter.Signal(); if (Interlocked.Decrement(ref this.activityWaiterCount) == 0) { activityWaiter.Dispose(); this.activityWaiter = null; } } base.OnAbort(); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { return new ChainedAsyncResult(timeout, callback, state, BeginCloseInput, EndCloseInput, OnBeginCloseContinue, OnEndCloseContinue); } IAsyncResult OnBeginCloseContinue(TimeSpan timeout, AsyncCallback callback, object state) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); return base.OnBeginClose(timeoutHelper.RemainingTime(), callback, state); } protected override void OnClose(TimeSpan timeout) { TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); this.CloseInput(timeoutHelper.RemainingTime()); base.OnClose(timeoutHelper.RemainingTime()); } protected override void OnEndClose(IAsyncResult result) { ChainedAsyncResult.End(result); } void OnEndCloseContinue(IAsyncResult result) { base.OnEndClose(result); } protected override void OnEmpty() { if (this.emptyCallback != null) this.emptyCallback(this.instanceContext); } void OnChannelClosed(object sender, EventArgs args) { this.RemoveChannel((IChannel)sender); } public bool RemoveChannel(IChannel channel) { lock (this.ThisLock) { if (this.firstIncomingChannel == channel) { this.firstIncomingChannel = null; this.ChannelRemoved(channel); return true; } else if (this.incomingChannels != null && this.incomingChannels.Contains(channel)) { this.incomingChannels.Remove(channel); return true; } else if (this.outgoingChannels != null && this.outgoingChannels.Contains(channel)) { this.outgoingChannels.Remove(channel); return true; } } return false; } public IChannel[] SnapshotChannels() { lock (this.ThisLock) { int outgoingCount = (this.outgoingChannels != null ? this.outgoingChannels.Count : 0); if (this.firstIncomingChannel != null) { IChannel[] channels = new IChannel[1 + outgoingCount]; channels[0] = this.firstIncomingChannel; if (outgoingCount > 0) this.outgoingChannels.CopyTo(channels, 1); return channels; } if (this.incomingChannels != null) { IChannel[] channels = new IChannel[this.incomingChannels.Count + outgoingCount]; this.incomingChannels.CopyTo(channels, 0); if (outgoingCount > 0) this.outgoingChannels.CopyTo(channels, this.incomingChannels.Count); return channels; } if (outgoingCount > 0) { IChannel[] channels = new IChannel[outgoingCount]; this.outgoingChannels.CopyTo(channels, 0); return channels; } } return EmptyArray .Allocate(0); } class ChannelCollection : SynchronizedCollection { ServiceChannelManager channelManager; public ChannelCollection(ServiceChannelManager channelManager, object mutex) : base(mutex) { this.channelManager = channelManager; } protected override void ClearItems() { lock (this.SyncRoot) { foreach (IChannel channel in this.Items) this.channelManager.ChannelRemoved(channel); base.ClearItems(); } } protected override void InsertItem(int index, IChannel channel) { lock (this.SyncRoot) { base.InsertItem(index, channel); this.channelManager.ChannelAdded(channel); } } protected override void RemoveItem(int index) { lock (this.SyncRoot) { IChannel channel = this.Items[index]; base.RemoveItem(index); this.channelManager.ChannelRemoved(channel); } } protected override void SetItem(int index, IChannel newChannel) { lock (this.SyncRoot) { IChannel oldChannel = this.Items[index]; base.SetItem(index, newChannel); this.channelManager.ChannelAdded(newChannel); this.channelManager.ChannelRemoved(oldChannel); } } } } } // 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
- SchemaImporterExtensionElement.cs
- RegexBoyerMoore.cs
- VisualBasicDesignerHelper.cs
- GetPageNumberCompletedEventArgs.cs
- PoisonMessageException.cs
- FileCodeGroup.cs
- Propagator.ExtentPlaceholderCreator.cs
- PageParser.cs
- TextViewBase.cs
- DocumentViewerBaseAutomationPeer.cs
- CodeTypeParameter.cs
- WebDisplayNameAttribute.cs
- DataServiceRequestOfT.cs
- RenderContext.cs
- SoapConverter.cs
- ClientRoleProvider.cs
- ProfileBuildProvider.cs
- Events.cs
- IPCCacheManager.cs
- VBIdentifierNameEditor.cs
- HorizontalAlignConverter.cs
- BindingSourceDesigner.cs
- MultipleViewProviderWrapper.cs
- CompositeFontInfo.cs
- Attachment.cs
- XhtmlBasicCalendarAdapter.cs
- Stylesheet.cs
- Decorator.cs
- DataGridViewComboBoxEditingControl.cs
- XmlUtf8RawTextWriter.cs
- DockingAttribute.cs
- StateDesigner.CommentLayoutGlyph.cs
- StreamProxy.cs
- WebPartDisplayModeEventArgs.cs
- XmlLoader.cs
- CacheVirtualItemsEvent.cs
- BindStream.cs
- TypeSource.cs
- Context.cs
- BehaviorService.cs
- PrePrepareMethodAttribute.cs
- XmlCollation.cs
- TextRangeSerialization.cs
- WindowsListViewGroup.cs
- RoleManagerModule.cs
- ExceptionHandlerDesigner.cs
- ByteRangeDownloader.cs
- DataStorage.cs
- ProxyWebPart.cs
- GCHandleCookieTable.cs
- DBSchemaTable.cs
- RequestStatusBarUpdateEventArgs.cs
- SamlDelegatingWriter.cs
- RemoteWebConfigurationHostServer.cs
- ControlBindingsConverter.cs
- DnsPermission.cs
- PenThreadPool.cs
- TemplateBindingExtension.cs
- NamespaceExpr.cs
- InkCanvas.cs
- ConnectionString.cs
- DataGridViewComboBoxCell.cs
- DataReaderContainer.cs
- TextTreeUndoUnit.cs
- Opcode.cs
- GZipStream.cs
- ItemsPresenter.cs
- ChannelSinkStacks.cs
- AttributeCollection.cs
- SiteMapHierarchicalDataSourceView.cs
- FeatureSupport.cs
- WindowsFormsSectionHandler.cs
- DbDataRecord.cs
- GeneralTransform3DCollection.cs
- DataObjectPastingEventArgs.cs
- ScriptResourceAttribute.cs
- SpecialTypeDataContract.cs
- RowToParametersTransformer.cs
- WebScriptEndpointElement.cs
- EnvironmentPermission.cs
- FlowStep.cs
- SyntaxCheck.cs
- HwndSource.cs
- EUCJPEncoding.cs
- AppSecurityManager.cs
- EncodingNLS.cs
- XmlSerializableServices.cs
- ProfilePropertyMetadata.cs
- CompilationPass2TaskInternal.cs
- RequestChannel.cs
- TimeSpanOrInfiniteValidator.cs
- HostingEnvironmentException.cs
- SortableBindingList.cs
- WeakRefEnumerator.cs
- HandleDictionary.cs
- SortedList.cs
- QilPatternVisitor.cs
- GraphicsPathIterator.cs
- SystemWebSectionGroup.cs
- UnsafeNativeMethods.cs