sam / do
watch download tarball
public
Description: DataObjects
Homepage: http://rubyforge.org/projects/dorb
Clone URL: git://github.com/sam/do.git
do / data_objects / lib / data_objects / support / pooling.rb
66a29ece » sam 2008-05-07 More pooling work! 1 require 'set'
2
32686eda » sam 2008-05-06 Working on a generic object... 3 class Object
4
5 module Pooling
6
721c5d3b » sam 2008-05-07 MustImplementDisposeError f... 7 class MustImplementDisposeError < StandardError
8 end
9
32686eda » sam 2008-05-06 Working on a generic object... 10 def self.included(target)
11 target.extend(ClassMethods)
12 end
13
069209c8 » sam 2008-05-07 More pooling work. 14 def release
66a29ece » sam 2008-05-07 More pooling work! 15 @__pool.release(self)
16 end
069209c8 » sam 2008-05-07 More pooling work. 17
32686eda » sam 2008-05-06 Working on a generic object... 18 class Pools
19
20 attr_reader :type
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 21 attr_accessor :size
32686eda » sam 2008-05-06 Working on a generic object... 22
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 23 def initialize(type, size = 4)
32686eda » sam 2008-05-06 Working on a generic object... 24 @type = type
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 25 @size = size
26 @pools = Hash.new { |h,k| h[k] = Pool.new(@size, @type, k) }
32686eda » sam 2008-05-06 Working on a generic object... 27 end
28
29 def flush!
30 @pools.each_pair do |args,pool|
31 pool.flush!
32 end
33
34 @pools.clear
35 self
36 end
37
38 def [](*args)
39 @pools[*args]
40 end
41
42 class Pool
43
44 attr_reader :type, :available, :reserved
45
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 46 def initialize(size, type, initializer)
47 @size = size
32686eda » sam 2008-05-06 Working on a generic object... 48 @type = type
66a29ece » sam 2008-05-07 More pooling work! 49 @initializer = initializer
50 @lock = Mutex.new
32686eda » sam 2008-05-06 Working on a generic object... 51 @available = []
66a29ece » sam 2008-05-07 More pooling work! 52 @reserved = Set.new
32686eda » sam 2008-05-06 Working on a generic object... 53 end
54
55 def flush!
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 56 @lock.synchronize do
57 reserved.each do |instance|
58 if @reserved.delete?(instance)
59 @available << instance
60 end
61 end
32686eda » sam 2008-05-06 Working on a generic object... 62
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 63 available.each do |instance|
64 instance.dispose
65 end
32686eda » sam 2008-05-06 Working on a generic object... 66
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 67 @available = []
68 @reserved = Set.new
69 end
32686eda » sam 2008-05-06 Working on a generic object... 70 end
069209c8 » sam 2008-05-07 More pooling work. 71
66a29ece » sam 2008-05-07 More pooling work! 72 def new
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 73 if @available.empty?
74 @lock.synchronize do
75 instance = nil
76
77 if @available.empty?
78 if @reserved.size < @size
79 instance = @type.allocate
80 instance.send(:initialize, *@initializer)
81 at_exit { instance.dispose }
82 instance.instance_variable_set("@__pool", self)
83 else
84 # until(instance) do
85 # TODO: Need to wait for an instance to become available,
86 # but to do that we need to not use a synchronization block.
87 # end
88
89 instance = @type.allocate
90 instance.send(:initialize, *@initializer)
91 at_exit { instance.dispose }
92 instance.instance_variable_set("@__pool", self)
93 end
94 else
95 instance = @available.pop
96 end
97
98 @reserved << instance
99 instance
069209c8 » sam 2008-05-07 More pooling work. 100 end
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 101 else
102 aquire_instance!
069209c8 » sam 2008-05-07 More pooling work. 103 end
104 end
105
66a29ece » sam 2008-05-07 More pooling work! 106 def release(instance)
107 @lock.synchronize do
108 if @reserved.delete?(instance)
109 @available << instance
069209c8 » sam 2008-05-07 More pooling work. 110 end
111 end
112 return nil
113 end
114
115 private
6dc7ddaa » sam 2008-05-07 Pretty close now. Need to p... 116 def aquire_instance!
117 instance = nil
118
119 @lock.synchronize do
120 instance = @available.pop
121 raise StandardError.new("Concurrency Error!") unless instance
122 @reserved << instance
123 end
124
125 instance
069209c8 » sam 2008-05-07 More pooling work. 126 end
32686eda » sam 2008-05-06 Working on a generic object... 127 end
128 end
129
130 module ClassMethods
721c5d3b » sam 2008-05-07 MustImplementDisposeError f... 131
132 def new(*args)
133 unless instance_methods.include?("dispose")
134 raise MustImplementDisposeError.new("#{self.name} must implement a `dispose' instance-method.")
135 end
069209c8 » sam 2008-05-07 More pooling work. 136
66a29ece » sam 2008-05-07 More pooling work! 137 pools[*args].new
069209c8 » sam 2008-05-07 More pooling work. 138 # uri = uri.is_a?(String) ? Addressable::URI::parse(uri) : uri
139 # DataObjects.const_get(uri.scheme.capitalize)::Connection.acquire(uri)
721c5d3b » sam 2008-05-07 MustImplementDisposeError f... 140 end
141
32686eda » sam 2008-05-06 Working on a generic object... 142 def pools
143 @pools ||= Pools.new(self)
144 end
145 end
146
147 end
148
149 end