public static async Task TestConcurrent(IResourcePool <int, Nothing> pool, int clients) { async Task Call() { int resource = -1; try { do { resource = pool.Acquire(); } while (resource < 0); await Task.Delay(_random.Next(10, 100)); } finally { pool.Release(resource); var stats = pool.Stats(); Assert.Equal(stats.Allocations, stats.Evictions + stats.Idle + stats.InUse); } } var tasks = new List <Task>(); for (var i = 0; i < clients; i++) { var task = Task.Run(Call); tasks.Add(task); } await Task.WhenAll(tasks); Assert.Equal(pool.Stats().Idle, pool.Size); }
/// <summary> /// Releases the resource back into the pool /// </summary> public void Dispose() { if (Log.IsDebugEnabled) { Log.DebugFormat("Closing socket {0}", _instanceId); } _pool.Release(this); }
/// <summary> /// 开始执行核心业务,此方法是为了封装统一的资源池操作 /// 1、如果传入的键存在,则在此方法里不会释放此键的资源,由外面释放 /// 2、如果传入的键不存在,则创建新的键,并在此方法里释放资源 /// </summary> /// <typeparam name="KeyT">键类型</typeparam> /// <typeparam name="ValueT">值类型</typeparam> /// <param name="resourcePool">资源池</param> /// <param name="action">处理业务回调</param> /// <param name="key">键</param> public static void StartExecCore <KeyT, ValueT>(this IResourcePool <KeyT, ValueT> resourcePool, Action <KeyT, ValueT> action, KeyT key = default(KeyT)) { bool keyExists; key = resourcePool.GetNewKey(out keyExists, key); try { var value = resourcePool.GetNewValue(key); action(key, value); } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { resourcePool.Release(key, keyExists); } }
public void TestRelease() { var resource = _pool.Acquire(); _pool.Release(resource); }
public IOperationResult Execute(IOperation op) { IOperationResult result = new BinaryOperationResult(); IPooledSocket socket = null; try { socket = _pool.Acquire(); if (Log.IsDebugEnabled) { Log.DebugFormat("Start execute {0} with {1}", op.Key, socket.InstanceId); } var buffers = op.GetBuffer(); socket.Write(buffers); result = op.ReadResponse(socket); if (result.Success) { result.Pass(); } } catch (NodeShutdownException e) { string msg = String.Format("Node Shutdown - {0}.", EndPoint); Log.DebugFormat("m:{0} i:{1}\n{2}", msg, op.Key, e); result.Fail(msg, e); result.StatusCode = StatusCode.NodeShutdown.ToInt(); } catch (QueueTimeoutException e) { string msg = String.Format("Queue Timeout - {0}.", EndPoint); Log.ErrorFormat("m:{0} i:{1}\n{2}", msg, op.Key, e); result.Fail(msg, e); result.StatusCode = StatusCode.SocketPoolTimeout.ToInt(); } catch (IOException e) { string msg = String.Format("Exception reading response - {0}", EndPoint); Log.ErrorFormat("m:{0} s:{1} i:{2}\n{3}", msg, op.Key, socket == null ? Guid.Empty : socket.InstanceId, e); result.Fail(msg, e); if (result.StatusCode == null || result.StatusCode == StatusCode.Success.ToInt()) { result.StatusCode = StatusCode.InternalError.ToInt(); } } catch (Exception e) { string msg = String.Format("Operation failed - {0}", EndPoint); Log.ErrorFormat("m:{0} s:{1} i:{2}\n{3}", msg, op.Key, socket == null ? Guid.Empty : socket.InstanceId, e); result.Fail(msg, e); if (result.StatusCode == null || result.StatusCode == StatusCode.Success.ToInt()) { result.StatusCode = StatusCode.InternalError.ToInt(); } } finally { if (socket != null) { if (Log.IsDebugEnabled) { Log.DebugFormat("End execute {0} with {1}", op.Key, socket.InstanceId); } _pool.Release(socket); } } if (Log.IsDebugEnabled) { const string msg = "Operation {0} :i {1} n: {2} t: {3} m: {4} sc: {5} r: {6}"; Log.DebugFormat(msg, result.Success ? op.RetryAttempts > 0 ? "succeeded*" : "succeeded" : op.RetryAttempts > 0 ? "failed*" : "failed", op.Key, _endpoint, Thread.CurrentThread.Name, result.Message, Enum.GetName(typeof(StatusCode), result.StatusCode ?? 0), op.RetryAttempts); } return(result); }