//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel { using System.Collections.Generic; using System.Runtime; using System.ServiceModel.Channels; using System.ServiceModel.Diagnostics.Application; sealed class ChannelFactoryRef<TChannel> where TChannel : class { ChannelFactory<TChannel> channelFactory; int refCount = 1; public ChannelFactoryRef(ChannelFactory<TChannel> channelFactory) { this.channelFactory = channelFactory; } public void AddRef() { this.refCount++; } // The caller should call Close/Abort when the return value is true. public bool Release() { --this.refCount; Fx.Assert(this.refCount >= 0, "RefCount should not be less than zero."); if (this.refCount == 0) { return true; } return false; } public void Close(TimeSpan timeout) { this.channelFactory.Close(timeout); } public void Abort() { this.channelFactory.Abort(); } public ChannelFactory<TChannel> ChannelFactory { get { return this.channelFactory; } } } class ChannelFactoryRefCache<TChannel> : MruCache<EndpointTrait<TChannel>, ChannelFactoryRef<TChannel>> where TChannel : class { static EndpointTraitComparer DefaultEndpointTraitComparer = new EndpointTraitComparer(); readonly int watermark; class EndpointTraitComparer : IEqualityComparer<EndpointTrait<TChannel>> { public bool Equals(EndpointTrait<TChannel> x, EndpointTrait<TChannel> y) { if (x != null) { if (y != null) return x.Equals(y); return false; } if (y != null) return false; return true; } public int GetHashCode(EndpointTrait<TChannel> obj) { if (obj == null) return 0; return obj.GetHashCode(); } } public ChannelFactoryRefCache(int watermark) : base(watermark * 4 / 5, watermark, DefaultEndpointTraitComparer) { this.watermark = watermark; } protected override void OnSingleItemRemoved(ChannelFactoryRef<TChannel> item) { // Remove from cache. if (item.Release()) { item.Abort(); } if (TD.ClientBaseCachedChannelFactoryCountIsEnabled()) { TD.ClientBaseCachedChannelFactoryCount(this.Count, this.watermark, this); } } protected override void OnItemAgedOutOfCache(ChannelFactoryRef<TChannel> item) { if (TD.ClientBaseChannelFactoryAgedOutofCacheIsEnabled()) { TD.ClientBaseChannelFactoryAgedOutofCache(this.watermark, this); } } } }