Documentation

For any request we cannot fullfill immediately, we have a set of lock
owners it is blocked on. We can pick one of the owners, the smallest say;
then we know that this request cannot possibly be fulfilled until this
owner does something. So we can index the pending requests by such a chosen
owner and only revisit them once the owner acts. For the requests to revisit
we need to do so in order of increasing priority; this order can be maintained
by the Set data structure, where we make use of the fact that tuples are ordered
lexicographically.

Additionally, we keep track of which owners have pending requests, to disallow
them any other lock tasks till their request is fulfilled. To allow canceling
of pending requests, we also keep track on which owner their request is pending
on and what the request was.

Update the locks on an onwer according to the given request, if possible.
Additionally (if the request succeeds) fulfill any pending requests that
became possible through this request. Return the new state of the waiting
structure, the result of the operation, and a list of owners to be notified.
The result is, as for lock allocation, the set of owners the request is
blocked on. Again, the type is chosen to be suitable for use in
atomicModifyIORef.
For convenience, fulfilled requests are always accepted.

Update locks as soon as possible. If the request cannot be fulfilled
immediately add the request to the waiting queue. The first argument is
the priority at which the owner is waiting, the remaining are as for
updateLocks, and so is the output.
For convenience, fulfilled requests are always accepted.