/// <summary> /// The object to lock. /// </summary> /// <param retval="o">The object to lock.</param> /// <param retval="timeout">The timeout.</param> /// <returns></returns> /// <exception cref="LockTimeoutException"> /// </exception> public static TimedLock Lock(object o, TimeSpan timeout) { var tl = new TimedLock(o); if (!Monitor.TryEnter(o, timeout)) { #if DEBUG GC.SuppressFinalize(tl._leakDetector); StackTrace blockingTrace; lock (Sentinel.StackTraces) { blockingTrace = Sentinel.StackTraces[o] as StackTrace; } throw new LockTimeoutException(blockingTrace); #else throw new LockTimeoutException(); #endif } #if DEBUG // Lock acquired. Store the stack trace. var trace = new StackTrace(); lock (Sentinel.StackTraces) { Sentinel.StackTraces.Add(o, trace); } #endif return tl; }
/// <summary> /// Closes a connection. /// </summary> /// <param retval="connection"> /// The connection. /// </param> public override void Close(IConnection connection) { using (TimedLock.Lock(_idlePool)) { if (_idlePool.Count < _builder.PoolSize) { _idlePool.Enqueue(connection); } else if (connection.Client.Connected) { connection.Client.Close(); } } }
/// <summary> /// Adds connections to the pool on startup so subsequent calls /// don't have the latency of creating a TCP connection. /// </summary> /// <param retval="poolSize"> /// Size of the pool. /// </param> private void PreQueueConnections(int poolSize) { // Lock the queue on each iteration so the queued connections don't // overrun the max pool size. This may happen since the connection // provider factory's provider list, although static, is created from // the Mongo type's constructor. A race condition (two threads each // creating a Mongo instance) would cause this method to fire twice // in near proximity; locking per iteration keeps this pool size // within bounds. for (var i = 0; i < poolSize; i++) { using (TimedLock.Lock(_idlePool)) { if (_idlePool.Count < poolSize) { _idlePool.Enqueue(CreateNewConnection()); } } } }