concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/lib/concurrent.rb +9 -29
  4. data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
  5. data/lib/concurrent/actor/actor_context.rb +77 -0
  6. data/lib/concurrent/actor/actor_ref.rb +67 -0
  7. data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
  8. data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
  9. data/lib/concurrent/actors.rb +5 -0
  10. data/lib/concurrent/agent.rb +81 -47
  11. data/lib/concurrent/async.rb +35 -35
  12. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  13. data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
  14. data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
  15. data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
  16. data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
  17. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  18. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  19. data/lib/concurrent/atomic/event.rb +103 -0
  20. data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
  21. data/lib/concurrent/atomics.rb +9 -0
  22. data/lib/concurrent/channel/buffered_channel.rb +6 -4
  23. data/lib/concurrent/channel/channel.rb +30 -2
  24. data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
  25. data/lib/concurrent/channel/waitable_list.rb +3 -1
  26. data/lib/concurrent/channels.rb +5 -0
  27. data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
  28. data/lib/concurrent/collection/priority_queue.rb +305 -0
  29. data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
  30. data/lib/concurrent/collections.rb +3 -0
  31. data/lib/concurrent/configuration.rb +68 -19
  32. data/lib/concurrent/dataflow.rb +9 -9
  33. data/lib/concurrent/delay.rb +21 -13
  34. data/lib/concurrent/dereferenceable.rb +40 -33
  35. data/lib/concurrent/exchanger.rb +3 -0
  36. data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
  37. data/lib/concurrent/executor/executor.rb +222 -0
  38. data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
  39. data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
  40. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  41. data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
  42. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  43. data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
  44. data/lib/concurrent/executor/one_by_one.rb +65 -0
  45. data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
  46. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  47. data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
  48. data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
  49. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
  50. data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
  51. data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
  52. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  53. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  54. data/lib/concurrent/executor/timer_set.rb +138 -0
  55. data/lib/concurrent/executors.rb +9 -0
  56. data/lib/concurrent/future.rb +39 -40
  57. data/lib/concurrent/ivar.rb +22 -15
  58. data/lib/concurrent/mvar.rb +2 -1
  59. data/lib/concurrent/obligation.rb +9 -3
  60. data/lib/concurrent/observable.rb +33 -0
  61. data/lib/concurrent/options_parser.rb +46 -0
  62. data/lib/concurrent/promise.rb +23 -24
  63. data/lib/concurrent/scheduled_task.rb +21 -45
  64. data/lib/concurrent/timer_task.rb +204 -126
  65. data/lib/concurrent/tvar.rb +1 -1
  66. data/lib/concurrent/utilities.rb +3 -36
  67. data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
  68. data/lib/concurrent/utility/timeout.rb +36 -0
  69. data/lib/concurrent/utility/timer.rb +21 -0
  70. data/lib/concurrent/version.rb +1 -1
  71. data/lib/concurrent_ruby_ext.bundle +0 -0
  72. data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
  73. data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
  74. data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
  75. data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
  76. data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
  77. data/spec/concurrent/agent_spec.rb +160 -71
  78. data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
  79. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
  80. data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
  81. data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
  82. data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
  83. data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
  84. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
  85. data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
  86. data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
  87. data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
  88. data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
  89. data/spec/concurrent/channel/channel_spec.rb +6 -4
  90. data/spec/concurrent/channel/probe_spec.rb +37 -9
  91. data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
  92. data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
  93. data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
  94. data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
  95. data/spec/concurrent/configuration_spec.rb +4 -70
  96. data/spec/concurrent/dereferenceable_shared.rb +5 -4
  97. data/spec/concurrent/exchanger_spec.rb +10 -5
  98. data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
  99. data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
  100. data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
  101. data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
  102. data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
  103. data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
  104. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
  105. data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
  106. data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
  107. data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
  108. data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
  109. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
  110. data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
  111. data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
  112. data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
  113. data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
  114. data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
  115. data/spec/concurrent/executor/timer_set_spec.rb +183 -0
  116. data/spec/concurrent/future_spec.rb +12 -0
  117. data/spec/concurrent/ivar_spec.rb +11 -1
  118. data/spec/concurrent/observable_shared.rb +173 -0
  119. data/spec/concurrent/observable_spec.rb +51 -0
  120. data/spec/concurrent/options_parser_spec.rb +71 -0
  121. data/spec/concurrent/runnable_shared.rb +6 -0
  122. data/spec/concurrent/scheduled_task_spec.rb +60 -40
  123. data/spec/concurrent/timer_task_spec.rb +130 -144
  124. data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
  125. data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
  126. data/spec/concurrent/utility/timer_spec.rb +52 -0
  127. metadata +147 -108
  128. data/lib/concurrent/actor_context.rb +0 -31
  129. data/lib/concurrent/actor_ref.rb +0 -39
  130. data/lib/concurrent/atomic.rb +0 -121
  131. data/lib/concurrent/channel/probe.rb +0 -19
  132. data/lib/concurrent/count_down_latch.rb +0 -60
  133. data/lib/concurrent/event.rb +0 -80
  134. data/lib/concurrent/java_cached_thread_pool.rb +0 -45
  135. data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
  136. data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
  137. data/lib/concurrent/simple_actor_ref.rb +0 -124
  138. data/lib/concurrent/thread_pool_executor.rb +0 -30
  139. data/spec/concurrent/atomic_spec.rb +0 -201
  140. data/spec/concurrent/count_down_latch_spec.rb +0 -125
  141. data/spec/concurrent/safe_task_executor_spec.rb +0 -58
  142. data/spec/concurrent/simple_actor_ref_spec.rb +0 -219
@@ -1,124 +0,0 @@
1
- require 'thread'
2
-
3
- require 'concurrent/actor_ref'
4
- require 'concurrent/event'
5
- require 'concurrent/ivar'
6
-
7
- module Concurrent
8
-
9
- class SimpleActorRef
10
- include ActorRef
11
-
12
- def initialize(actor, opts = {})
13
- @actor = actor
14
- @mutex = Mutex.new
15
- @queue = Queue.new
16
- @thread = nil
17
- @stop_event = Event.new
18
- @abort_on_exception = opts.fetch(:abort_on_exception, true)
19
- @reset_on_error = opts.fetch(:reset_on_error, true)
20
- @exception_class = opts.fetch(:rescue_exception, false) ? Exception : StandardError
21
- @observers = CopyOnNotifyObserverSet.new
22
-
23
- @actor.define_singleton_method(:shutdown, &method(:set_stop_event))
24
- end
25
-
26
- def running?
27
- ! @stop_event.set?
28
- end
29
-
30
- def shutdown?
31
- @stop_event.set?
32
- end
33
-
34
- def post(*msg, &block)
35
- raise ArgumentError.new('message cannot be empty') if msg.empty?
36
- @mutex.synchronize do
37
- supervise unless shutdown?
38
- end
39
- ivar = IVar.new
40
- @queue.push(Message.new(msg, ivar, block))
41
- ivar
42
- end
43
-
44
- def post!(seconds, *msg)
45
- raise Concurrent::TimeoutError if seconds == 0
46
- ivar = self.post(*msg)
47
- ivar.value(seconds)
48
- if ivar.incomplete?
49
- raise Concurrent::TimeoutError
50
- elsif ivar.reason
51
- raise ivar.reason
52
- end
53
- ivar.value
54
- end
55
-
56
- def shutdown
57
- @mutex.synchronize do
58
- return if shutdown?
59
- if @thread && @thread.alive?
60
- @thread.kill
61
- @actor.on_shutdown
62
- end
63
- @stop_event.set
64
- end
65
- end
66
-
67
- def join(timeout = nil)
68
- @stop_event.wait(timeout)
69
- end
70
-
71
- private
72
-
73
- Message = Struct.new(:payload, :ivar, :callback)
74
-
75
- def set_stop_event
76
- @stop_event.set
77
- end
78
-
79
- def supervise
80
- if @thread.nil?
81
- @actor.on_start
82
- @thread = new_worker_thread
83
- elsif ! @thread.alive?
84
- @actor.on_reset
85
- @thread = new_worker_thread
86
- end
87
- end
88
-
89
- def new_worker_thread
90
- Thread.new do
91
- Thread.current.abort_on_exception = @abort_on_exception
92
- run_message_loop
93
- end
94
- end
95
-
96
- def run_message_loop
97
- loop do
98
- message = @queue.pop
99
- result = ex = nil
100
-
101
- begin
102
- result = @actor.receive(*message.payload)
103
- rescue @exception_class => ex
104
- @actor.on_error(Time.now, message.payload, ex)
105
- @actor.on_reset if @reset_on_error
106
- ensure
107
- now = Time.now
108
- message.ivar.complete(ex.nil?, result, ex)
109
-
110
- begin
111
- message.callback.call(now, result, ex) if message.callback
112
- rescue @exception_class => ex
113
- # suppress
114
- end
115
-
116
- observers.notify_observers(now, message.payload, result, ex)
117
- end
118
-
119
- break if @stop_event.set?
120
- end
121
- @actor.on_shutdown
122
- end
123
- end
124
- end
@@ -1,30 +0,0 @@
1
- require 'concurrent/ruby_thread_pool_executor'
2
-
3
- module Concurrent
4
-
5
- if RUBY_PLATFORM == 'java'
6
- require 'concurrent/java_thread_pool_executor'
7
- # @!macro [attach] thread_pool_executor
8
- #
9
- # A thread pool...
10
- #
11
- # The API and behavior of this class are based on Java's +ThreadPoolExecutor+
12
- #
13
- # @note When running on the JVM (JRuby) this class will inherit from +JavaThreadPoolExecutor+.
14
- # On all other platforms it will inherit from +RubyThreadPoolExecutor+.
15
- #
16
- # @see Concurrent::RubyThreadPoolExecutor
17
- # @see Concurrent::JavaThreadPoolExecutor
18
- #
19
- # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
20
- # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
21
- # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
22
- # @see http://stackoverflow.com/questions/17957382/fixedthreadpool-vs-fixedthreadpool-the-lesser-of-two-evils
23
- class ThreadPoolExecutor < JavaThreadPoolExecutor
24
- end
25
- else
26
- # @!macro thread_pool_executor
27
- class ThreadPoolExecutor < RubyThreadPoolExecutor
28
- end
29
- end
30
- end
@@ -1,201 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe AtomicFixnum do
6
-
7
- context 'construction' do
8
-
9
- it 'sets the initial value' do
10
- AtomicFixnum.new(10).value.should eq 10
11
- end
12
-
13
- it 'defaults the initial value to zero' do
14
- AtomicFixnum.new.value.should eq 0
15
- end
16
-
17
- it 'raises en exception if the initial value is not a Fixnum' do
18
- lambda {
19
- AtomicFixnum.new(10.01)
20
- }.should raise_error(ArgumentError)
21
- end
22
-
23
- if jruby?
24
-
25
- it 'uses Java AtomicLong' do
26
- mutex = double('mutex')
27
- Mutex.stub(:new).with(no_args).and_return(mutex)
28
- mutex.should_not_receive(:synchronize)
29
- AtomicFixnum.new.value
30
- end
31
-
32
- else
33
-
34
- it 'is synchronized' do
35
- mutex = double('mutex')
36
- Mutex.stub(:new).with(no_args).and_return(mutex)
37
- mutex.should_receive(:synchronize)
38
- AtomicFixnum.new.value
39
- end
40
-
41
- end
42
-
43
- end
44
-
45
- context '#value' do
46
-
47
- it 'returns the current value' do
48
- counter = AtomicFixnum.new(10)
49
- counter.value.should eq 10
50
- counter.increment
51
- counter.value.should eq 11
52
- counter.decrement
53
- counter.value.should eq 10
54
- end
55
- end
56
-
57
- context '#value=' do
58
-
59
- it 'sets the #value to the given `Fixnum`' do
60
- atomic = AtomicFixnum.new(0)
61
- atomic.value = 10
62
- atomic.value.should eq 10
63
- end
64
-
65
- it 'returns the new value' do
66
- atomic = AtomicFixnum.new(0)
67
- (atomic.value = 10).should eq 10
68
- end
69
-
70
- it 'raises and exception if the value is not a `Fixnum`' do
71
- atomic = AtomicFixnum.new(0)
72
- expect {
73
- atomic.value = 'foo'
74
- }.to raise_error(ArgumentError)
75
- end
76
- end
77
-
78
- context '#increment' do
79
-
80
- it 'increases the value by one' do
81
- counter = AtomicFixnum.new(10)
82
- 3.times{ counter.increment }
83
- counter.value.should eq 13
84
- end
85
-
86
- it 'returns the new value' do
87
- counter = AtomicFixnum.new(10)
88
- counter.increment.should eq 11
89
- end
90
-
91
- it 'is aliased as #up' do
92
- AtomicFixnum.new(10).up.should eq 11
93
- end
94
-
95
- if jruby?
96
-
97
- it 'does not use Mutex class' do
98
- mutex = double('mutex')
99
- Mutex.stub(:new).with(no_args).and_return(mutex)
100
- mutex.should_not_receive(:synchronize)
101
- AtomicFixnum.new.increment
102
- end
103
-
104
- else
105
-
106
- it 'is synchronized' do
107
- mutex = double('mutex')
108
- Mutex.stub(:new).with(no_args).and_return(mutex)
109
- mutex.should_receive(:synchronize)
110
- AtomicFixnum.new.increment
111
- end
112
-
113
- end
114
-
115
- end
116
-
117
- context '#decrement' do
118
-
119
- it 'decreases the value by one' do
120
- counter = AtomicFixnum.new(10)
121
- 3.times{ counter.decrement }
122
- counter.value.should eq 7
123
- end
124
-
125
- it 'returns the new value' do
126
- counter = AtomicFixnum.new(10)
127
- counter.decrement.should eq 9
128
- end
129
-
130
- it 'is aliased as #down' do
131
- AtomicFixnum.new(10).down.should eq 9
132
- end
133
-
134
- if jruby?
135
-
136
- it 'does not use Mutex class' do
137
- mutex = double('mutex')
138
- Mutex.stub(:new).with(no_args).and_return(mutex)
139
- mutex.should_not_receive(:synchronize)
140
- AtomicFixnum.new.decrement
141
- end
142
-
143
- else
144
-
145
- it 'is synchronized' do
146
- mutex = double('mutex')
147
- Mutex.stub(:new).with(no_args).and_return(mutex)
148
- mutex.should_receive(:synchronize)
149
- AtomicFixnum.new.decrement
150
- end
151
-
152
- end
153
-
154
- end
155
-
156
- context '#compare_and_set' do
157
-
158
- it 'returns false if the value is not found' do
159
- AtomicFixnum.new(14).compare_and_set(2, 14).should eq false
160
- end
161
-
162
- it 'returns true if the value is found' do
163
- AtomicFixnum.new(14).compare_and_set(14, 2).should eq true
164
- end
165
-
166
- it 'sets if the value is found' do
167
- f = AtomicFixnum.new(14)
168
- f.compare_and_set(14, 2)
169
- f.value.should eq 2
170
- end
171
-
172
- it 'does not set if the value is not found' do
173
- f = AtomicFixnum.new(14)
174
- f.compare_and_set(2, 12)
175
- f.value.should eq 14
176
- end
177
-
178
- if jruby?
179
-
180
- it 'does not use Mutex class' do
181
- mutex = double('mutex')
182
- Mutex.stub(:new).with(no_args).and_return(mutex)
183
- mutex.should_not_receive(:synchronize)
184
- AtomicFixnum.new(14).compare_and_set(14, 2)
185
- end
186
-
187
- else
188
-
189
- it 'is synchronized' do
190
- mutex = double('mutex')
191
- Mutex.stub(:new).with(no_args).and_return(mutex)
192
- mutex.should_receive(:synchronize)
193
- AtomicFixnum.new(14).compare_and_set(14, 2)
194
- end
195
-
196
- end
197
-
198
- end
199
-
200
- end
201
- end
@@ -1,125 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe CountDownLatch do
6
-
7
- let(:latch) { CountDownLatch.new(3) }
8
- let(:zero_count_latch) { CountDownLatch.new(0) }
9
-
10
- context '#initialize' do
11
-
12
- it 'raises an exception if the initial count is less than zero' do
13
- expect {
14
- CountDownLatch.new(-1)
15
- }.to raise_error(ArgumentError)
16
- end
17
-
18
- it 'raises an exception if the initial count is not an integer' do
19
- expect {
20
- CountDownLatch.new('foo')
21
- }.to raise_error(ArgumentError)
22
- end
23
- end
24
-
25
- describe '#count' do
26
-
27
- it 'should be the value passed to the constructor' do
28
- latch.count.should eq 3
29
- end
30
-
31
- it 'should be decreased after every count down' do
32
- latch.count_down
33
- latch.count.should eq 2
34
- end
35
-
36
- it 'should not go below zero' do
37
- 5.times { latch.count_down }
38
- latch.count.should eq 0
39
- end
40
- end
41
-
42
- describe '#wait' do
43
-
44
- context 'count set to zero' do
45
- it 'should return true immediately' do
46
- result = zero_count_latch.wait
47
- result.should be_true
48
- end
49
-
50
- it 'should return true immediately with timeout' do
51
- result = zero_count_latch.wait(5)
52
- result.should be_true
53
- end
54
- end
55
-
56
- context 'non zero count' do
57
-
58
- it 'should block thread until counter is set to zero' do
59
- 3.times do
60
- Thread.new { sleep(0.1); latch.count_down }
61
- end
62
-
63
- result = latch.wait
64
- result.should be_true
65
- latch.count.should eq 0
66
- end
67
-
68
- it 'should block until counter is set to zero with timeout' do
69
- 3.times do
70
- Thread.new { sleep(0.1); latch.count_down }
71
- end
72
-
73
- result = latch.wait(1)
74
- result.should be_true
75
- latch.count.should eq 0
76
-
77
- end
78
-
79
- it 'should block until timeout and return false when counter is not set to zero' do
80
- result = latch.wait(0.1)
81
- result.should be_false
82
- latch.count.should eq 3
83
- end
84
- end
85
- end
86
-
87
- context 'spurious wake ups' do
88
-
89
- before(:each) do
90
- def latch.simulate_spurious_wake_up
91
- @mutex.synchronize do
92
- @condition.signal
93
- @condition.broadcast
94
- end
95
- end
96
- end
97
-
98
- it 'should resist to spurious wake ups without timeout' do
99
- @expected = false
100
- Thread.new { latch.wait; @expected = true }
101
-
102
- sleep(0.1)
103
- latch.simulate_spurious_wake_up
104
-
105
- sleep(0.1)
106
- @expected.should be_false
107
- end
108
-
109
- it 'should resist to spurious wake ups with timeout' do
110
- @expected = false
111
- Thread.new { latch.wait(0.5); @expected = true }
112
-
113
- sleep(0.1)
114
- latch.simulate_spurious_wake_up
115
-
116
- sleep(0.1)
117
- @expected.should be_false
118
-
119
- sleep(0.4)
120
- @expected.should be_true
121
- end
122
- end
123
-
124
- end
125
- end