From bf301275348e02e06db6111627026ac94a0d194a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Thu, 28 Mar 2019 11:13:20 +0100 Subject: [PATCH] Add ConnectionPool.removeUnused. Allows to disconnect all connections that are not currently in use. In particular, it allows to close all connections at shutdown to avoid leaking socket descriptors. --- source/vibe/core/connectionpool.d | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/source/vibe/core/connectionpool.d b/source/vibe/core/connectionpool.d index 1cd0f76..373a024 100644 --- a/source/vibe/core/connectionpool.d +++ b/source/vibe/core/connectionpool.d @@ -101,6 +101,28 @@ final class ConnectionPool(Connection) auto ret = LockedConnection!Connection(this, conn); return ret; } + + /** Removes all currently unlocked connections from the pool. + + Params: + disconnect_callback = Gets called for every removed connection to + allow closing connections and freeing associated resources. + */ + void removeUnused(scope void delegate(Connection conn) @safe nothrow disconnect_callback) + { + Connection[] remaining_conns, removed_conns; + foreach (c; m_connections) { + if (m_lockCount.get(c, 0) > 0) + remaining_conns ~= c; + else + removed_conns ~= c; + } + + m_connections = remaining_conns; + + foreach (c; removed_conns) + disconnect_callback(c); + } } /// @@ -137,6 +159,31 @@ unittest { // issue vibe-d#2109 new ConnectionPool!TCPConnection({ return connectTCP("127.0.0.1", 8080); }); } +unittest { // removeUnused + class Connection {} + + auto pool = new ConnectionPool!Connection({ + return new Connection; // perform the connection here + }); + + auto c1 = pool.lockConnection(); + auto c1i = c1.__conn; + + auto c2 = pool.lockConnection(); + auto c2i = c2.__conn; + + + assert(pool.m_connections == [c1i, c2i]); + + c2 = LockedConnection!Connection.init; + pool.removeUnused((c) { assert(c is c2i); }); + assert(pool.m_connections == [c1i]); + + c1 = LockedConnection!Connection.init; + pool.removeUnused((c) { assert(c is c1i); }); + assert(pool.m_connections == []); +} + struct LockedConnection(Connection) { import vibe.core.task : Task;