Module: Extlib::Pooling

Defined in:
lib/extlib/pooling.rb

Overview

Notes

Provides pooling support to class it got included in.

Pooling of objects is a faster way of aquiring instances of objects compared to regular allocation and initialization because instances are keeped in memory reused.

Classes that include Pooling module have re-defined new method that returns instances acquired from pool.

Term resource is used for any type of poolable objects and should NOT be thought as DataMapper Resource or ActiveResource resource and such.

In Data Objects connections are pooled so that it is unnecessary to allocate and initialize connection object each time connection is needed, like per request in a web application.

Pool obviously has to be thread safe because state of object is reset when it is released.

Defined Under Namespace

Classes: InvalidResourceError, Pool

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.append_pool(pool) ⇒ Object


71
72
73
74
75
76
# File 'lib/extlib/pooling.rb', line 71

def self.append_pool(pool)
  lock.synchronize do
    pools << pool
  end
  Extlib::Pooling.scavenger
end

.included(target) ⇒ Object


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/extlib/pooling.rb', line 85

def self.included(target)
  target.class_eval do
    class << self
      alias __new new
    end

    @__pools     = {}
    @__pool_lock = Mutex.new
    @__pool_wait = ConditionVariable.new

    def self.__pool_lock
      @__pool_lock
    end

    def self.__pool_wait
      @__pool_wait
    end

    def self.new(*args)
      (@__pools[args] ||= __pool_lock.synchronize { Pool.new(self.pool_size, self, args) }).new
    end

    def self.__pools
      @__pools
    end

    def self.pool_size
      8
    end
  end
end

.lockObject


78
79
80
# File 'lib/extlib/pooling.rb', line 78

def self.lock
  @lock ||= Mutex.new
end

.poolsObject


67
68
69
# File 'lib/extlib/pooling.rb', line 67

def self.pools
  @pools ||= Set.new
end

.scavengerObject


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
# File 'lib/extlib/pooling.rb', line 32

def self.scavenger
  unless scavenger?
    @scavenger = Thread.new do
      running = true
      while running do
        # Sleep before we actually start doing anything.
        # Otherwise we might clean up something we just made
        sleep(scavenger_interval)

        lock.synchronize do
          pools.each do |pool|
            # This is a useful check, but non-essential, and right now it breaks lots of stuff.
            # if pool.expired?
            pool.lock.synchronize do
              if pool.expired?
                pool.dispose
              end
            end
            # end
          end

          # The pool is empty, we stop the scavenger
          # It wil be restarted if new resources are added again
          if pools.empty?
            running = false
          end
        end
      end # loop
    end
  end

  @scavenger.priority = -10
  @scavenger
end

.scavenger?Boolean


28
29
30
# File 'lib/extlib/pooling.rb', line 28

def self.scavenger?
  defined?(@scavenger) && !@scavenger.nil? && @scavenger.alive?
end

.scavenger_intervalObject


231
232
233
# File 'lib/extlib/pooling.rb', line 231

def self.scavenger_interval
  60
end

Instance Method Details

#detachObject


121
122
123
# File 'lib/extlib/pooling.rb', line 121

def detach
  @__pool.delete(self) unless @__pool.nil?
end

#releaseObject


117
118
119
# File 'lib/extlib/pooling.rb', line 117

def release
  @__pool.release(self) unless @__pool.nil?
end