File: pool.rb

package info (click to toggle)
ruby-ftw 0.0.49-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 548 kB
  • sloc: ruby: 1,922; makefile: 5
file content (68 lines) | stat: -rw-r--r-- 1,972 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
require "ftw/namespace"
require "thread"

# A simple thread-safe resource pool.
#
# Resources in this pool must respond to 'available?'.
# For best results, your resources should just 'include FTW::Poolable'
#
# The primary use case was as a way to pool FTW::Connection instances.
class FTW::Pool
  def initialize
    # Pool is a hash of arrays.
    @pool = Hash.new { |h,k| h[k] = Array.new }
    @lock = Mutex.new
  end # def initialize

  # Add an object to the pool with a given identifier. For example:
  #
  #     pool.add("www.google.com:80", connection1)
  #     pool.add("www.google.com:80", connection2)
  #     pool.add("github.com:443", connection3)
  def add(identifier, object)
    @lock.synchronize do
      @pool[identifier] << object
    end
    return object
  end # def add

  # Fetch a resource from this pool. If no available resources
  # are found, the 'default_block' is invoked and expected to
  # return a new resource to add to the pool that satisfies
  # the fetch..
  #
  # Example:
  #
  #     pool.fetch("github.com:443") do 
  #       conn = FTW::Connection.new("github.com:443")
  #       conn.secure
  #       conn
  #     end
  def fetch(identifier, &default_block)
    @lock.synchronize do
      @pool[identifier].delete_if { |o| o.available? && !o.connected? }
      object = @pool[identifier].find { |o| o.available? }
      return object if !object.nil?
    end
    # Otherwise put the return value of default_block in the
    # pool and return it, but don't put nil values in the pool.
    obj = default_block.call
    if obj.nil?
      return nil
    else
      return add(identifier, obj)
    end
  end # def fetch

  # Iterate over all pool members.
  #
  # This holds the pool lock during this method, so you should not call 'fetch'
  # or 'add'.
  def each(&block)
    @lock.synchronize do
      @pool.each do |identifier, object|
        block.call(identifier, object)
      end
    end
  end # def each
end # class FTW::Pool