Permalink
Browse files

changed lock option to :wait => {true,false,Numeric}

  • Loading branch information...
slyphon committed Aug 29, 2012
1 parent 6042c21 commit 76e33764f54b0a82c12f6777bc9fe0ae37adb7a6
@@ -88,7 +88,7 @@ def shared_locker(name)
# @example with timeout
#
# begin
- # zk.with_lock('foo', :timeout => 5.0) do |lock|
+ # zk.with_lock('foo', :wait => 5.0) do |lock|
# # this code is executed while holding the lock
# end
# rescue ZK::Exceptions::LockWaitTimeoutError
@@ -97,8 +97,8 @@ def shared_locker(name)
#
# @raise [ArgumentError] if `opts[:mode]` is not one of the expected values
#
- # @raise [ZK::Exceptions::LockWaitTimeoutError] if :timeout is exceeded
- # without acquiring the lock
+ # @raise [ZK::Exceptions::LockWaitTimeoutError] if :wait timeout is
+ # exceeded without acquiring the lock
#
def with_lock(name, opts={}, &b)
opts = opts.dup
View
@@ -160,6 +160,7 @@ class WeAreTheLowestLockNumberException < StandardError
end # Locker
end # ZK
+require 'zk/locker/lock_options'
require 'zk/locker/locker_base'
require 'zk/locker/shared_locker'
require 'zk/locker/exclusive_locker'
@@ -47,12 +47,12 @@ def acquirable?
def lock_with_opts_hash(opts)
create_lock_path!(EXCLUSIVE_LOCK_PREFIX)
- block, timeout = opts.values_at(:block, :timeout)
+ lock_opts = LockOptions.new(opts)
if got_write_lock?
- synchronize { @locked = true }
- elsif block
- block_until_write_lock!(:timeout => timeout)
+ @mutex.synchronize { @locked = true }
+ elsif lock_opts.blocking?
+ block_until_write_lock!(:timeout => lock_opts.timeout)
else
cleanup_lock_path!
false
@@ -0,0 +1,36 @@
+module ZK
+ module Locker
+ # @private
+ class LockOptions
+ attr_reader :wait, :now, :timeout
+
+ def initialize(opts={})
+ @timeout = nil
+ @now = Time.now
+
+ raise "BLAH!" if opts.has_key?(:block)
+
+ if opts.has_key?(:timeout)
+ raise ArgumentError, ":timeout is an invalid option, use :wait with a numeric argument"
+ end
+
+ case w = opts[:wait]
+ when TrueClass, FalseClass, nil
+ @wait = false|w
+ when Numeric
+ if w < 0
+ raise ArgumentError, ":wait must be a positive float or integer, or zero, not: #{w.inspect}"
+ end
+ @wait = true
+ @timeout = w.to_f
+ else
+ raise ArgumentError, ":wait must be true, false, nil, or Numeric, not #{w.inspect}"
+ end
+ end
+
+ def blocking?
+ @wait
+ end
+ end
+ end
+end
@@ -67,12 +67,20 @@ def initialize(client, name, root_lock_node=nil)
#
# @yield [lock] calls the block with the lock instance when acquired
#
- # @option opts [Numeric] :timeout (nil) if non-nil, the amount of time to
- # wait for the lock to be acquired.
- #
- # @raise [LockWaitTimeoutError] if the :timeout is exceeded
+ # @option opts [Numeric,true] :wait (nil) if non-nil, the amount of time to
+ # wait for the lock to be acquired. since with_lock is only blocking,
+ # `false` isn't a valid option. `true` is ignored (as it is the default).
+ # If a Numeric (float or integer) option is given, maximum amount of time
+ # to wait for lock acquisition.
+ #
+ # @raise [LockWaitTimeoutError] if the :wait timeout is exceeded
+ # @raise [ArgumentError] if :wait is false (since you can't do non-blocking)
def with_lock(opts={})
- opts = opts.merge(:block => true)
+ if opts[:wait].kind_of?(FalseClass)
+ raise ArgumentError, ":wait cannot be false, with_lock is only used in blocking mode"
+ end
+
+ opts = { :wait => true }.merge(opts)
lock(opts)
yield self
ensure
@@ -162,12 +170,11 @@ def unlock!
# @deprecated in favor of the options hash style
#
# @overload lock(opts={})
- # @option opts [true,false] :block (false) if true we block the
- # caller until we obtain a lock on the resource
- #
- # @option opts [Numeric] :timeout (nil) if given, the number of seconds
- # we should wait for the lock to be acquired. Will raise
- # LockWaitTimeoutError if we exceed the timeout.
+ # @option opts [true,false,Numeric] :wait (false) If true we block the
+ # caller until we obtain a lock on the resource. If false, we do not
+ # block. If a Numeric, the number of seconds we should wait for the
+ # lock to be acquired. Will raise LockWaitTimeoutError if we exceed
+ # the timeout.
#
# @since 1.7
#
@@ -190,7 +197,7 @@ def lock(opts={})
case opts
when TrueClass, FalseClass # old style boolean argument
- opts = { :block => opts }
+ opts = { :wait => opts }
end
lock_with_opts_hash(opts)
@@ -84,12 +84,12 @@ def got_read_lock?
def lock_with_opts_hash(opts)
create_lock_path!(SHARED_LOCK_PREFIX)
- block, timeout = opts.values_at(:block, :timeout)
+ lock_opts = LockOptions.new(opts)
if got_read_lock?
- @locked = true
- elsif block
- block_until_read_lock!(:timeout => timeout)
+ @mutex.synchronize { @locked = true }
+ elsif lock_opts.blocking?
+ block_until_read_lock!(:timeout => lock_opts.timeout)
else
# we didn't get the lock, and we're not gonna wait around for it, so
# clean up after ourselves
@@ -119,7 +119,7 @@
locker.lock.should be_false
th = Thread.new do
- locker.lock(:block => true)
+ locker.lock(:wait => true)
ary << :locked
end
@@ -143,7 +143,7 @@
th = Thread.new do
begin
- locker.lock(:block => true, :timeout => 0.01)
+ locker.lock(:wait => 0.01)
ary << :locked
rescue Exception => e
@exc = e
@@ -83,7 +83,7 @@
thread = Thread.new do
begin
- @zk.with_lock(@path_to_lock, :timeout => 0.01) do |lock|
+ @zk.with_lock(@path_to_lock, :wait => 0.01) do |lock|
raise "NO NO NO!! should not have called the block!!"
end
rescue Exception => e
@@ -116,7 +116,7 @@
array.length.should == 2
end
- it %[should accept a :timeout option] do
+ it %[should accept a :wait option] do
array = []
first_lock = @zk.locker("mylock")
first_lock.lock.should be_true
@@ -125,7 +125,7 @@
thread = Thread.new do
begin
- second_lock.with_lock(:timeout => 0.01) do
+ second_lock.with_lock(:wait => 0.01) do
array << :second_lock
end
rescue Exception => e
@@ -124,7 +124,7 @@
locker.lock.should be_false
th = Thread.new do
- locker.lock(:block => true)
+ locker.lock(:wait => true)
ary << :locked
end
@@ -152,7 +152,7 @@
th = Thread.new do
begin
- locker.lock(:block => true, :timeout => 0.01)
+ locker.lock(:wait => 0.01)
ary << :locked
rescue Exception => e
@exc = e

0 comments on commit 76e3376

Please sign in to comment.