Thread-safe async/await lock. Functions which are waiting for the lock are suspended, and are resumed when the lock is released, in order. Many readers can hold the lock at the same time; however locking for writing is exclusive. When a read lock is held, it will not be released until the reader queue is empty. When a write lock is held, it will not be released until the writer queue is empty. TODO: make this API also work in blocking I/O mode