refactor Zk::NodeDeletionWatcher to be able to watch multiple nodes, firing event when only a certain number of the watched nodes remain (defaults to zero). This enables further work on a Semaphore pattern.
Add test case that shows off bug in shared-lock/exclusive-lock integration wherein an exclusive lock is granted before all lower locks are cleared.
refactor shared functionality from ExclusiveLocker and SharedLocker back into LockerBase, relying on NodeDeletionWatcher's new multi-delete and default threshold of zero-remaining to ensure that we don't give out a lock until all locks that block have been released (for shared locks, this is all write locks lower than our own; for exclusive locks this is all locks lower than our own)
add SemaphoreLocker and associated specs. Note the TODO item regarding root_lock_node conflict.
in SemaphoreLocker#got_semaphore?, don't assume we have a lock path already
Incorporate feedback from @eric, making Zk::NodeDeletionWatcher's :threshold option be the default when nil or false are passed.
remove first declaration of twice-defined method
more cleanup; moving functionality shared across various lockers into ZK::Locker::LockerBase
Cleanup based on review of slyphon/zk#56
Merge branch 'dev/semaphore'