diff --git a/README.md b/README.md index a0ac7da..75cfdc8 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,8 @@ Create a pool of objects to share amongst the fibers or threads in your Ruby app Then use the pool in your application: - @memcached.with do |dalli| - dalli.fetch('some-count', :expires_in => 1.day) do - SomeModel.query.count - end + @memcached.with_connection do |dalli| + dalli.get('some-count') end diff --git a/lib/connection_pool.rb b/lib/connection_pool.rb index dafbd06..12c2e16 100644 --- a/lib/connection_pool.rb +++ b/lib/connection_pool.rb @@ -42,6 +42,7 @@ class ConnectionPool ensure checkin end + alias_method :with_connection, :with def method_missing(name, *args) checkout.send(name, *args) diff --git a/lib/connection_pool/timed_queue.rb b/lib/connection_pool/timed_queue.rb index ba8c787..3d0d751 100644 --- a/lib/connection_pool/timed_queue.rb +++ b/lib/connection_pool/timed_queue.rb @@ -4,7 +4,6 @@ require 'timeout' class TimedQueue def initialize @que = [] - @waiting = [] @mutex = Mutex.new @resource = ConditionVariable.new end @@ -15,22 +14,15 @@ class TimedQueue @resource.signal end end - alias << push + alias_method :<<, :push def timed_pop(timeout=0.5) - while true - @mutex.synchronize do - @waiting.delete(Thread.current) - if @que.empty? - @waiting.push Thread.current - @resource.wait(@mutex, timeout) - raise Timeout::Error if @que.empty? - else - retval = @que.shift - @resource.signal - return retval - end + @mutex.synchronize do + if @que.empty? + @resource.wait(@mutex, timeout) + raise Timeout::Error if @que.empty? end + return @que.shift end end diff --git a/test/test_connection_pool.rb b/test/test_connection_pool.rb index b35d945..c78fb89 100644 --- a/test/test_connection_pool.rb +++ b/test/test_connection_pool.rb @@ -3,38 +3,46 @@ require 'helper' class TestConnectionPool < MiniTest::Unit::TestCase class NetworkConnection + def initialize + @x = 0 + end def do_something - sleep 0.1 - 'foo' + @x += 1 + sleep 0.05 + @x + end + def fast + @x += 1 end end def test_basic_multithreaded_usage pool = ConnectionPool.new(:size => 5) { NetworkConnection.new } threads = [] - 10.times do + 15.times do threads << Thread.new do - pool.with do |net| + pool.with_connection do |net| net.do_something end end end a = Time.now - threads.each(&:join) + result = threads.map(&:value) b = Time.now - assert((b - a) > 0.2) + assert_operator((b - a), :>, 0.125) + assert_equal(result, [1,2,3].cycle(5).sort) end def test_timeout - pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new } + pool = ConnectionPool.new(:timeout => 0.05, :size => 1) { NetworkConnection.new } Thread.new do pool.with do |net| net.do_something - sleep 0.2 + sleep 0.1 end end - sleep 0.1 + sleep 0.05 assert_raises Timeout::Error do pool.do_something end @@ -42,6 +50,15 @@ class TestConnectionPool < MiniTest::Unit::TestCase def test_passthru pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new } - assert_equal 'foo', pool.do_something + assert_equal 1, pool.do_something + assert_equal 2, pool.do_something + end + + def test_return_value + pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new } + result = pool.with_connection do |net| + net.fast + end + assert_equal 1, result end end \ No newline at end of file