public Connection borrowConnection(long timeout, TimeUnit unit)
      throws ConnectionException, TimeoutException {
    if (isShutdown.get())
      // Note: throwing a ConnectionException is probably fine in practice as it will trigger the
      // creation of a new host.
      // That being said, maybe having a specific exception could be cleaner.
      throw new ConnectionException(host.getAddress(), "Pool is shutdown");

    if (connections.isEmpty()) {
      for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++) {
        // We don't respect MAX_SIMULTANEOUS_CREATION here because it's  only to
        // protect against creating connection in excess of core too quickly
        scheduledForCreation.incrementAndGet();
        manager.executor().submit(newConnectionTask);
      }
      Connection c = waitForConnection(timeout, unit);
      c.setKeyspace(manager.poolsState.keyspace);
      return c;
    }

    int minInFlight = Integer.MAX_VALUE;
    Connection leastBusy = null;
    for (Connection connection : connections) {
      int inFlight = connection.inFlight.get();
      if (inFlight < minInFlight) {
        minInFlight = inFlight;
        leastBusy = connection;
      }
    }

    if (minInFlight >= options().getMaxSimultaneousRequestsPerConnectionThreshold(hostDistance)
        && connections.size() < options().getMaxConnectionsPerHost(hostDistance))
      maybeSpawnNewConnection();

    while (true) {
      int inFlight = leastBusy.inFlight.get();

      if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) {
        leastBusy = waitForConnection(timeout, unit);
        break;
      }

      if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) break;
    }
    leastBusy.setKeyspace(manager.poolsState.keyspace);
    return leastBusy;
  }