Acquire acquires the semaphore, blocking until resources are available.
Returns nil if acquire was successful or ctx.Err if the context was cancelled
in the meantime.
Enqueue reserves the next place in the queue and returns a Ticket used to
acquire access to the resource when it's the callers turn. The Ticket has to
be supplied to Release before discarding.
Release releases the semaphore and notifies the next in line if any.
If the ticket was already released the function returns an error. After the
ticket is released it should be discarded.