fix writelock to only release the lock when the object is disposed.  and added a check to make sure the object only gets disposed once and is unusable after it has been disposed.
experimental change to getting the write lock.  actually, I dislike this code and intend to replace it soon.  but it's interesting, so I'm committing it as part of the journey.  instead of returning the write lock or None or throw, the caller provides a function to be called when the writelock is available.  the big thing we lose here is the using (var tx=getWriteLock) syntax, which I liked.  next attempt will be an async/Task.
this code has the structure I want (wait on a task/async for the write lock), but it seems to have a thread safety problem.  still working on this.
test was broken.  core code seems to be okay.  bad fmt string was causing an exception.  worse, I was trying to write 500 segments when only 200-ish will fit, and the db header code can't deal with automatically merging when needed yet.
back to using a waiting list of callbacks, except now with TaskCompletionSource it's awaitable.
turn the write lock waiting list into a queue.  using the queue from FSharpx.
implement ReplaceSegments in IWriteLock so that segment merge can do what it needs.  but this probably doesn't want to be 'public' in IWriteLock.  merge returns and async.  it isn't called from anywhere yet.  the expectation is that it will be RunSynchronously when the header gets full, but will be run in the background when we simply need to merge segments for maintenance purposes.