Class: Authorize::ResourcePool
- Inherits:
-
Object
- Object
- Authorize::ResourcePool
- Extended by:
- Forwardable
- Defined in:
- lib/authorize/resource_pool.rb
Overview
Arbitrate thread-safe access to a limited set of expensive and perishable objects
Instance Attribute Summary collapse
-
#num_waiting ⇒ Object
readonly
Returns the value of attribute num_waiting.
Instance Method Summary collapse
- #available ⇒ Object
-
#checkin(obj) ⇒ Object
Return an object to the pool.
-
#checkout(*args) ⇒ Object
Checkout an object from the pool.
-
#clear! ⇒ Object
Remove all resources from the pool and revoke all tokens TODO: don’t brutally/blindly revoke tokens -raise an exception or fire a callback, and address waiting threads.
-
#expire ⇒ Object
Expire resources in inventory with the given block.
-
#freshen ⇒ Object
Freshen objects in inventory with the given block.
-
#initialize(max_size, factory) ⇒ ResourcePool
constructor
Create a new unfilled resource pool with a capacity of of at most max_size objects.
- #size ⇒ Object
Constructor Details
#initialize(max_size, factory) ⇒ ResourcePool
Create a new unfilled resource pool with a capacity of of at most max_size objects. The pool is lazily filled by the factory lambda.
17 18 19 20 21 22 23 24 25 |
# File 'lib/authorize/resource_pool.rb', line 17 def initialize(max_size, factory) @factory = factory @pool = [] @tokens = [] @monitor = Monitor.new @tokens_cv = @monitor.new_cond @num_waiting = 0 max_size.times {|i| @tokens.unshift(i)} end |
Instance Attribute Details
#num_waiting ⇒ Object (readonly)
Returns the value of attribute num_waiting.
13 14 15 |
# File 'lib/authorize/resource_pool.rb', line 13 def num_waiting @num_waiting end |
Instance Method Details
#available ⇒ Object
31 32 33 |
# File 'lib/authorize/resource_pool.rb', line 31 def available @tokens.size end |
#checkin(obj) ⇒ Object
Return an object to the pool
51 52 53 54 55 56 57 58 |
# File 'lib/authorize/resource_pool.rb', line 51 def checkin(obj) @monitor.synchronize do token = @pool.index(obj) raise "#{obj} has not been checked out from this pool" unless token && !@tokens.include?(token) @tokens.push(token) if token @tokens_cv.signal end end |
#checkout(*args) ⇒ Object
Checkout an object from the pool. Arguments are passed unmolested to ConditionVariable#wait to manage timeouts.
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/authorize/resource_pool.rb', line 36 def checkout(*args) @monitor.synchronize do until token = @tokens.pop begin @num_waiting += 1 raise "Timed out during checkout" unless @tokens_cv.wait(*args) ensure @num_waiting -= 1 end end @pool[token] ||= @factory.call end end |
#clear! ⇒ Object
Remove all resources from the pool and revoke all tokens TODO: don’t brutally/blindly revoke tokens -raise an exception or fire a callback, and address waiting threads.
79 80 81 82 83 84 85 |
# File 'lib/authorize/resource_pool.rb', line 79 def clear! @monitor.synchronize do @pool.each_index {|i| @tokens << i} @tokens.uniq! @pool.clear end end |
#expire ⇒ Object
Expire resources in inventory with the given block. Available (not reserved) pool members are yielded to the block. The object is expired (removed permanently from the pool) if the block returns a true-ish value.
63 64 65 66 67 68 69 70 |
# File 'lib/authorize/resource_pool.rb', line 63 def expire @monitor.synchronize do @tokens.each do |i| next unless obj = @pool[i] @pool[i] = nil if yield obj end end end |
#freshen ⇒ Object
Freshen objects in inventory with the given block
73 74 75 |
# File 'lib/authorize/resource_pool.rb', line 73 def freshen expire {|obj| yield(obj) ; return false} end |
#size ⇒ Object
27 28 29 |
# File 'lib/authorize/resource_pool.rb', line 27 def size @pool.compact.length end |