> I'm probably just being thick... but doesn't this deadlock?

synchronization is bloody hard, so if something looks fishy, it is better to always ask, that way the author is forced to explain his reasoning

> If some other thread is currently establishing a connection (and there aren't any free), we'll wait on `@available.poll(@checkout_timeout)` (a timeout which, given our use case here, seems a little precarious to me anyway...)

yes, waiting for others is somewhat unfortunate, however in order to have a correct implementation of `disconnect!` and `clear_reloadable_connections!` I would argue that it requires to gain control of all connections, if this isn't possible within `@checkout_timeout` limit, then a `ConnectionTimeoutError` is in order. Waiting without a timeout is probably worse as if there is some misbehaving thread, that is alive and not releasing its connection, `clear_reloadable_connections!` and `disconnect!` would deadlock.

I would also argue that the previous implementation was not correct, consider:
 * `thread_A` checks out a connection (`conn_X`) and is using it (and therefore is outside of `synchronize` sections and is not checking `conn.owner` and not repeatedly calling `connection` or `with_connection`),
 * `thread_B` calls `clear_reloadable_connections!` (prev. implementation would just do `@reserved_connections.clear` and then simply `checkin(conn_X)`) and then does `checkout` (or `connection`, it doesn't matter) and gets the same connection (`conn_X`) that `thread_A` is still __legitimately__ using...

The same applies for `disconnect!` - correct implementation __must__ wait for all threads to voluntarily release their connections (it is identical to a process shutdown: the process can be only terminate if only and only if all its threads have terminated).

I'll see if I can add test cases for that.

> but when the connecting thread finishes establishing its connection, it'll need to adopt it, which it can't do because we're asleep inside a `synchronize`.

This one is tricky and while working on this it got me stomped as well. Unfortunately this can't happen because the `@available` queue is using the same `Monitor` (`@lock`) instance as the `ConnPool`, its `ConditionVariable` (`@cond = @lock.new_cond`) is derived from this same `@lock`, therefore under the `Monitor` contract, when one wants to use `@cond.wait()` one is required to hold the `@lock` and a call of `@cond.wait()` releases `@lock` when going to sleep and re-acquires it on wake-up. All in all: `@cond.wait()` inside `synchronize` releases the pool's lock and does not block other threads.