Class: DataObjects::Pooling::Pool

Inherits:
Object
  • Object
show all
Defined in:
lib/data_objects/pooling.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_size, resource, args) ⇒ Pool

Returns a new instance of Pool.

Raises:

  • (ArgumentError)


135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/data_objects/pooling.rb', line 135

def initialize(max_size, resource, args)
  raise ArgumentError, "+max_size+ should be an Integer but was #{max_size.inspect}" unless max_size.is_a?(Integer)
  raise ArgumentError, "+resource+ should be a Class but was #{resource.inspect}" unless resource.is_a?(Class)

  @max_size = max_size
  @resource = resource
  @args = args

  @available = []
  @used      = {}
  DataObjects::Pooling.append_pool(self)
end

Instance Attribute Details

#availableObject (readonly)

Returns the value of attribute available.



133
134
135
# File 'lib/data_objects/pooling.rb', line 133

def available
  @available
end

#usedObject (readonly)

Returns the value of attribute used.



133
134
135
# File 'lib/data_objects/pooling.rb', line 133

def used
  @used
end

Instance Method Details

#delete(instance) ⇒ Object



199
200
201
202
203
204
205
206
# File 'lib/data_objects/pooling.rb', line 199

def delete(instance)
  lock.synchronize do
    instance.instance_variable_set(:@__pool, nil)
    @used.delete(instance.object_id)
    wait.signal
  end
  nil
end

#disposeObject



221
222
223
224
225
# File 'lib/data_objects/pooling.rb', line 221

def dispose
  flush!
  @resource.__pools.delete(@args)
  !DataObjects::Pooling.pools.delete?(self).nil?
end

#expired?Boolean

Returns:

  • (Boolean)


227
228
229
230
231
232
233
234
235
236
# File 'lib/data_objects/pooling.rb', line 227

def expired?
  @available.each do |instance|
    next unless DataObjects.exiting ||
                instance.instance_variable_get(:@__allocated_in_pool) + DataObjects::Pooling.scavenger_interval <= (Time.now + 0.02)

    instance.dispose
    @available.delete(instance)
  end
  size.zero?
end

#flush!Object



217
218
219
# File 'lib/data_objects/pooling.rb', line 217

def flush!
  @available.pop.dispose until @available.empty?
end

#inspectObject



213
214
215
# File 'lib/data_objects/pooling.rb', line 213

def inspect
  "#<DataObjects::Pooling::Pool<#{@resource.name}> available=#{@available.size} used=#{@used.size} size=#{@max_size}>"
end

#lockObject



148
149
150
# File 'lib/data_objects/pooling.rb', line 148

def lock
  @resource.__pool_lock
end

#newObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/data_objects/pooling.rb', line 160

def new
  instance = nil
  loop do
    lock.synchronize do
      if @available.size.positive?
        instance = @available.pop
        @used[instance.object_id] = instance
      elsif @used.size < @max_size
        instance = @resource.__new(*@args)
        raise InvalidResourceError, "#{@resource} constructor created a nil object" if instance.nil?
        raise InvalidResourceError, "#{instance} is already part of the pool" if @used.include? instance

        instance.instance_variable_set(:@__pool, self)
        instance.instance_variable_set(:@__allocated_in_pool, Time.now)
        @used[instance.object_id] = instance
      else
        # Wait for another thread to release an instance.
        # If we exhaust the pool and don't release the active instance,
        # we'll wait here forever, so it's *very* important to always
        # release your services and *never* exhaust the pool within
        # a single thread.
        wait.wait(lock)
      end
    end
    break if instance
  end
  instance
end

#release(instance) ⇒ Object



189
190
191
192
193
194
195
196
197
# File 'lib/data_objects/pooling.rb', line 189

def release(instance)
  lock.synchronize do
    instance.instance_variable_set(:@__allocated_in_pool, Time.now)
    @used.delete(instance.object_id)
    @available.push(instance) unless @available.include?(instance)
    wait.signal
  end
  nil
end

#scavenge_intervalObject



156
157
158
# File 'lib/data_objects/pooling.rb', line 156

def scavenge_interval
  @resource.scavenge_interval
end

#sizeObject Also known as: length



208
209
210
# File 'lib/data_objects/pooling.rb', line 208

def size
  @used.size + @available.size
end

#waitObject



152
153
154
# File 'lib/data_objects/pooling.rb', line 152

def wait
  @resource.__pool_wait
end