improve waitgroup

This commit is contained in:
Loic Nageleisen 2015-12-17 08:54:10 +01:00
parent aa3bb21334
commit 0bbee7df48
2 changed files with 25 additions and 21 deletions

View file

@ -5,16 +5,19 @@ class WaitGroup
@waiting = [] @waiting = []
end end
def add(count) def add(delta)
sync! { @count += count } sync! do
@count += delta
fail 'negative WaitGroup counter' if @count < 0
if @waiting.any? && delta > 0 && @count == delta
fail 'misuse: add called concurrently with wait'
end
wake!
end
end end
def done def done
sync! do add(-1)
fail 'negative count' if done?
@count -= 1
wake!
end
end end
private def done? private def done?

View file

@ -2,6 +2,9 @@ require 'test/unit'
require 'thread' require 'thread'
require 'channel/waitgroup' require 'channel/waitgroup'
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
class TestWaitGroup < Test::Unit::TestCase class TestWaitGroup < Test::Unit::TestCase
module Util module Util
def meanwhile(*procs, &blk) def meanwhile(*procs, &blk)
@ -24,27 +27,25 @@ class TestWaitGroup < Test::Unit::TestCase
def test_waitgroup def test_waitgroup
Time.now.tap do |start| Time.now.tap do |start|
wg = WaitGroup.new wg = WaitGroup.new
wg.add(5) wg.add(2)
ok1 = false ok1 = false
ok2 = false ok2 = false
ok3 = false go -> { sleep 0.3; ok1 = true; wg.done }
ok4 = false go -> { sleep 0.5; ok2 = true; wg.done }
ok5 = false
go -> { sleep 0.1; ok1 = true; wg.done }
go -> { sleep 0.2; ok2 = true; wg.done }
go -> { sleep 0.3; ok3 = true; wg.done }
go -> { sleep 0.4; ok4 = true; wg.done }
go -> { sleep 0.5; ok5 = true; wg.done }
wg.wait wg.wait
duration = Time.now - start duration = Time.now - start
assert_equal(true, duration > 0.45) assert_equal(true, duration > 0.48)
assert_equal(true, duration < 0.70) assert_equal(true, duration < 0.52)
assert_true(ok1) assert_true(ok1)
assert_true(ok2) assert_true(ok2)
assert_true(ok3)
assert_true(ok4)
assert_true(ok5)
assert_raises(RuntimeError) { wg.done } assert_raises(RuntimeError) { wg.done }
end end
end end
def test_waitgroup_concurrent_add
wg = WaitGroup.new
go -> { wg.wait }
sleep 0.1
assert_raises(RuntimeError) { wg.add(1) }
end
end end