@@ -49,8 +49,7 @@ pub const Client = struct {
4949 http_proxy : ? Uri ,
5050 root_ca : tls.config.CertBundle ,
5151 tls_verify_host : bool = true ,
52- idle_connections : IdleConnections ,
53- connection_pool : std .heap .MemoryPool (Connection ),
52+ connection_manager : ConnectionManager ,
5453
5554 const Opts = struct {
5655 tls_verify_host : bool = true ,
@@ -65,17 +64,16 @@ pub const Client = struct {
6564 const state_pool = try StatePool .init (allocator , max_concurrent );
6665 errdefer state_pool .deinit (allocator );
6766
68- const idle_connections = IdleConnections .init (allocator , opts .max_idle_connection );
69- errdefer idle_connections .deinit ();
67+ const connection_manager = ConnectionManager .init (allocator , opts .max_idle_connection );
68+ errdefer connection_manager .deinit ();
7069
7170 return .{
7271 .root_ca = root_ca ,
7372 .allocator = allocator ,
7473 .state_pool = state_pool ,
7574 .http_proxy = opts .http_proxy ,
76- .idle_connections = idle_connections ,
7775 .tls_verify_host = opts .tls_verify_host ,
78- .connection_pool = std . heap . MemoryPool ( Connection ). init ( allocator ) ,
76+ .connection_manager = connection_manager ,
7977 };
8078 }
8179
@@ -85,8 +83,7 @@ pub const Client = struct {
8583 self .root_ca .deinit (allocator );
8684 }
8785 self .state_pool .deinit (allocator );
88- self .idle_connections .deinit ();
89- self .connection_pool .deinit ();
86+ self .connection_manager .deinit ();
9087 }
9188
9289 pub fn request (self : * Client , method : Request.Method , uri : * const Uri ) ! Request {
@@ -307,36 +304,33 @@ pub const Request = struct {
307304 self ._connection = null ;
308305
309306 if (self ._keepalive == false ) {
310- self .destroyConnection (connection );
307+ self ._client . connection_manager . destroy (connection );
311308 return ;
312309 }
313310
314- self ._client .idle_connections . put (connection ) catch | err | {
311+ self ._client .connection_manager . keepIdle (connection ) catch | err | {
315312 self .destroyConnection (connection );
316313 log .err ("failed to release connection to pool: {}" , .{err });
317314 };
318315 }
319316
320317 fn createConnection (self : * Request , socket : posix.socket_t , blocking : bool ) ! * Connection {
321318 const client = self ._client ;
322- const connection = try client .connection_pool .create ();
323- errdefer client .connection_pool .destroy (connection );
319+ const connection , const owned_host = try client .connection_manager .create (self ._connect_host );
324320
325321 connection .* = .{
326322 .tls = null ,
327323 .socket = socket ,
328324 .blocking = blocking ,
325+ .host = owned_host ,
329326 .port = self ._connect_port ,
330- .host = try client .allocator .dupe (u8 , self ._connect_host ),
331327 };
332328
333329 return connection ;
334330 }
335331
336332 fn destroyConnection (self : * Request , connection : * Connection ) void {
337- const client = self ._client ;
338- connection .deinit (client .allocator );
339- client .connection_pool .destroy (connection );
333+ self ._client .connection_manager .destroy (connection );
340334 }
341335
342336 const AddHeaderOpts = struct {
@@ -403,9 +397,10 @@ pub const Request = struct {
403397 posix .close (socket );
404398 return err ;
405399 };
400+ self ._connection = connection ;
406401
407402 if (self ._secure ) {
408- connection .tls = .{
403+ self . _connection .? .tls = .{
409404 .blocking = try tls .client (std.net.Stream { .handle = socket }, .{
410405 .host = self ._connect_host ,
411406 .root_ca = self ._client .root_ca ,
@@ -415,7 +410,6 @@ pub const Request = struct {
415410 };
416411 }
417412
418- self ._connection = connection ;
419413 self ._connection_from_keepalive = false ;
420414 }
421415
@@ -605,7 +599,7 @@ pub const Request = struct {
605599 return null ;
606600 }
607601
608- return self ._client .idle_connections .get (self ._secure , self ._connect_host , self ._connect_port , blocking );
602+ return self ._client .connection_manager .get (self ._secure , self ._connect_host , self ._connect_port , blocking );
609603 }
610604
611605 fn createSocket (self : * Request , blocking : bool ) ! struct { posix .socket_t , std .net .Address } {
@@ -2219,29 +2213,31 @@ const StatePool = struct {
22192213// always re-use the connection (just toggle the socket's blocking status), but
22202214// for TLS, we'd need to see if the two different TLS objects (blocking and non
22212215// blocking) can be converted from each other.
2222- const IdleConnections = struct {
2216+ const ConnectionManager = struct {
22232217 max : usize ,
22242218 idle : List ,
22252219 count : usize ,
22262220 mutex : Thread.Mutex ,
22272221 allocator : Allocator ,
22282222 node_pool : std .heap .MemoryPool (Node ),
2223+ connection_pool : std .heap .MemoryPool (Connection ),
22292224
22302225 const List = std .DoublyLinkedList (* Connection );
22312226 const Node = List .Node ;
22322227
2233- fn init (allocator : Allocator , max : usize ) IdleConnections {
2228+ fn init (allocator : Allocator , max : usize ) ConnectionManager {
22342229 return .{
22352230 .max = max ,
22362231 .count = 0 ,
22372232 .idle = .{},
22382233 .mutex = .{},
22392234 .allocator = allocator ,
22402235 .node_pool = std .heap .MemoryPool (Node ).init (allocator ),
2236+ .connection_pool = std .heap .MemoryPool (Connection ).init (allocator ),
22412237 };
22422238 }
22432239
2244- fn deinit (self : * IdleConnections ) void {
2240+ fn deinit (self : * ConnectionManager ) void {
22452241 const allocator = self .allocator ;
22462242
22472243 self .mutex .lock ();
@@ -2253,9 +2249,10 @@ const IdleConnections = struct {
22532249 node = next ;
22542250 }
22552251 self .node_pool .deinit ();
2252+ self .connection_pool .deinit ();
22562253 }
22572254
2258- fn get (self : * IdleConnections , secure : bool , host : []const u8 , port : u16 , blocking : bool ) ? * Connection {
2255+ fn get (self : * ConnectionManager , secure : bool , host : []const u8 , port : u16 , blocking : bool ) ? * Connection {
22592256 self .mutex .lock ();
22602257 defer self .mutex .unlock ();
22612258
@@ -2273,28 +2270,41 @@ const IdleConnections = struct {
22732270 return null ;
22742271 }
22752272
2276- fn put (self : * IdleConnections , connection : * Connection ) ! void {
2273+ fn keepIdle (self : * ConnectionManager , connection : * Connection ) ! void {
22772274 self .mutex .lock ();
22782275 defer self .mutex .unlock ();
22792276
22802277 var node : * Node = undefined ;
22812278 if (self .count == self .max ) {
22822279 const oldest = self .idle .popFirst () orelse {
22832280 std .debug .assert (self .max == 0 );
2284- connection . deinit ( self .allocator );
2281+ self .destroy ( connection );
22852282 return ;
22862283 };
2287- oldest . data . deinit ( self . allocator );
2284+ self . destroy ( oldest . data );
22882285 // re-use the node
22892286 node = oldest ;
22902287 } else {
2291- self .count += 1 ;
22922288 node = try self .node_pool .create ();
2289+ self .count += 1 ;
22932290 }
22942291
22952292 node .data = connection ;
22962293 self .idle .append (node );
22972294 }
2295+
2296+ fn create (self : * ConnectionManager , host : []const u8 ) ! struct { * Connection , []const u8 } {
2297+ const connection = try self .connection_pool .create ();
2298+ errdefer self .connection_pool .destroy (connection );
2299+
2300+ const owned_host = try self .allocator .dupe (u8 , host );
2301+ return .{ connection , owned_host };
2302+ }
2303+
2304+ fn destroy (self : * ConnectionManager , connection : * Connection ) void {
2305+ connection .deinit (self .allocator );
2306+ self .connection_pool .destroy (connection );
2307+ }
22982308};
22992309
23002310const testing = @import ("../testing.zig" );
0 commit comments