1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Activities
{
using System;
using System.Collections.Generic;
using System.Runtime;
using System.Runtime.Collections;
public sealed class SendMessageChannelCache : IDisposable, ICancelable
{
static Func<SendMessageChannelCache> defaultExtensionProvider = new Func<SendMessageChannelCache>(CreateDefaultExtension);
ChannelCacheSettings channelCacheSettings;
ChannelCacheSettings factoryCacheSettings;
bool isReadOnly;
bool allowUnsafeCaching;
bool isDisposed;
ObjectCache<InternalSendMessage.FactoryCacheKey, InternalSendMessage.ChannelFactoryReference> factoryCache;
object thisLock;
public SendMessageChannelCache()
: this(null, null, ChannelCacheDefaults.DefaultAllowUnsafeSharing)
{
}
public SendMessageChannelCache(ChannelCacheSettings factorySettings, ChannelCacheSettings channelSettings) :
this(factorySettings, channelSettings, ChannelCacheDefaults.DefaultAllowUnsafeSharing)
{
}
// use the default settings if null is specified for FactoryCacheSettings or ChannelCacheSettings
public SendMessageChannelCache(ChannelCacheSettings factorySettings, ChannelCacheSettings channelSettings, bool allowUnsafeCaching)
{
this.allowUnsafeCaching = allowUnsafeCaching;
this.FactorySettings = factorySettings;
this.ChannelSettings = channelSettings;
this.thisLock = new Object();
}
internal static Func<SendMessageChannelCache> DefaultExtensionProvider
{
get
{
return defaultExtensionProvider;
}
}
public bool AllowUnsafeCaching
{
get
{
return this.allowUnsafeCaching;
}
set
{
ThrowIfReadOnly();
this.allowUnsafeCaching = value;
}
}
public ChannelCacheSettings ChannelSettings
{
get
{
return this.channelCacheSettings;
}
set
{
ThrowIfReadOnly();
if (value == null)
{
this.channelCacheSettings = new ChannelCacheSettings { LeaseTimeout = ChannelCacheDefaults.DefaultChannelLeaseTimeout };
}
else
{
this.channelCacheSettings = value;
}
}
}
public ChannelCacheSettings FactorySettings
{
get
{
return this.factoryCacheSettings;
}
set
{
ThrowIfReadOnly();
if (value == null)
{
this.factoryCacheSettings = new ChannelCacheSettings { LeaseTimeout = ChannelCacheDefaults.DefaultFactoryLeaseTimeout };
}
else
{
this.factoryCacheSettings = value;
}
}
}
static SendMessageChannelCache CreateDefaultExtension()
{
SendMessageChannelCache defaultExtension = new SendMessageChannelCache();
defaultExtension.FactorySettings.LeaseTimeout = ChannelCacheDefaults.DefaultFactoryLeaseTimeout;
defaultExtension.ChannelSettings.LeaseTimeout = ChannelCacheDefaults.DefaultChannelLeaseTimeout;
return defaultExtension;
}
// factory cache will be created on first usage after which the settings are immutable
internal ObjectCache<InternalSendMessage.FactoryCacheKey, InternalSendMessage.ChannelFactoryReference> GetFactoryCache()
{
if (this.factoryCache == null)
{
this.isReadOnly = true;
lock (thisLock)
{
ThrowIfDisposed();
if (this.factoryCache == null)
{
// we don't need to set DisposeItemCallback since InternalSendMessage.ChannelFactoryReference is IDisposable
ObjectCacheSettings objectCacheSettings = new ObjectCacheSettings
{
CacheLimit = this.FactorySettings.MaxItemsInCache,
IdleTimeout = this.FactorySettings.IdleTimeout,
LeaseTimeout = this.FactorySettings.LeaseTimeout
};
this.factoryCache = new ObjectCache<InternalSendMessage.FactoryCacheKey, InternalSendMessage.ChannelFactoryReference>(objectCacheSettings);
}
}
}
return this.factoryCache;
}
void ThrowIfReadOnly()
{
if (this.isReadOnly)
{
// cache has already been created, settings cannot be changed now
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CacheSettingsLocked));
}
}
public void Dispose()
{
// Close the ChannelFactory and the Channels
// SendMessageChannelCache cannot be used after Dispose is called
if (!this.isDisposed)
{
lock (thisLock)
{
if (!this.isDisposed)
{
if (this.factoryCache != null)
{
this.factoryCache.Dispose();
}
this.isDisposed = true;
}
}
}
}
void ICancelable.Cancel()
{
Dispose();
}
void ThrowIfDisposed()
{
if (this.isDisposed == true)
{
throw FxTrace.Exception.AsError(new ObjectDisposedException(typeof(SendMessageChannelCache).ToString()));
}
}
}
}
|