class Async::HTTP::Pool


#reusable? -> can be used again.
#multiplex -> 1 or more.
Resources must respond to
This pool doesn’t impose a maximum number of open resources, but it WILL block if there are no available resources and trying to allocate another one fails.
In general we don’t know the policy until connection is established.
- Multiplex requests per connection (HTTP2)
- Multiple sequential requests per connection (HTTP1 with keep-alive)
- Single request per connection (HTTP/1 without keep-alive)
Pool behaviours

def acquire

def acquire
	resource = wait_for_next_available
	
	return resource unless block_given?
	
	begin
		yield resource
	ensure
		release(resource)
	end
end

def close

def close
	@available.each_key(&:close)
	@available.clear
end

def create_resource

def create_resource
	begin
		# This might fail, which is okay :)
		resource = @constructor.call
	rescue StandardError
		Async.logger.error "#{$!}: #{$!.backtrace}"
		return nil
	end
	
	@available[resource] = 1
	
	return resource
end

def initialize(limit = nil, &block)

def initialize(limit = nil, &block)
	@available = {} # resource => count
	@waiting = []
	
	@limit = limit
	
	@constructor = block
end

def next_available

TODO this does not take into account resources that start off good but can fail.
def next_available
	@available.each do |resource, count|
		if count < resource.multiplex
			@available[resource] += 1
			
			return resource
		end
	end
	
	if !@limit or @available.count < @limit
		Async.logger.debug(self) {"No available resources, allocating new one..."}
		return create_resource
	end
end

def release(resource)

Make the resource available and let waiting tasks know that there is something available.
def release(resource)
	if resource.reusable?
		Async.logger.debug(self) {"Reusing resource #{resource}"}
		
		@available[resource] -= 1
		
		if task = @waiting.pop
			task.resume
		end
	else
		Async.logger.debug(self) {"Closing resource: #{resource}"}
		resource.close
	end
end

def wait_for_next_available

def wait_for_next_available
	until resource = next_available
		@waiting << Fiber.current
		Task.yield
	end
	
	return resource
end