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

Sign up to get free protection for your applications and to get access to all the features.
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,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require_relative 'dereferenceable_shared'
3
+ require_relative 'observable_shared'
3
4
 
4
5
  module Concurrent
5
6
 
@@ -18,6 +19,17 @@ module Concurrent
18
19
  end.new
19
20
  end
20
21
 
22
+ context '#send_off' do
23
+ subject { Agent.new 2 }
24
+
25
+ it 'executes post and post-off in order' do
26
+ subject.post { |v| v + 2 }
27
+ subject.post_off { |v| v * 3 }
28
+ subject.await
29
+ subject.value.should eq 12
30
+ end
31
+ end
32
+
21
33
  context 'behavior' do
22
34
 
23
35
  # dereferenceable
@@ -33,11 +45,22 @@ module Concurrent
33
45
  end
34
46
 
35
47
  def execute_dereferenceable(subject)
36
- subject.post{|value| 10 }
48
+ subject.post { |value| 10 }
37
49
  sleep(0.1)
38
50
  end
39
51
 
40
52
  it_should_behave_like :dereferenceable
53
+
54
+ # observable
55
+
56
+ subject { Agent.new(0) }
57
+
58
+ def trigger_observable(observable)
59
+ observable.post { nil }
60
+ sleep(0.1)
61
+ end
62
+
63
+ it_should_behave_like :observable
41
64
  end
42
65
 
43
66
  context '#initialize' do
@@ -59,25 +82,25 @@ module Concurrent
59
82
  it 'uses the executor given with the :executor option' do
60
83
  executor.should_receive(:post).with(any_args).and_return(0)
61
84
  agent = Agent.new(0, executor: executor)
62
- agent.post{|value| 0 }
85
+ agent.post { |value| 0 }
63
86
  end
64
87
 
65
88
  it 'uses the global operation pool when :operation is true' do
66
89
  Concurrent.configuration.should_receive(:global_operation_pool).and_return(executor)
67
90
  agent = Agent.new(0, operation: true)
68
- agent.post{|value| 0 }
91
+ agent.post { |value| 0 }
69
92
  end
70
93
 
71
94
  it 'uses the global task pool when :task is true' do
72
95
  Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
73
96
  agent = Agent.new(0, task: true)
74
- agent.post{|value| 0 }
97
+ agent.post { |value| 0 }
75
98
  end
76
99
 
77
100
  it 'uses the global task pool by default' do
78
101
  Concurrent.configuration.should_receive(:global_task_pool).and_return(executor)
79
102
  agent = Agent.new(0)
80
- agent.post{|value| 0 }
103
+ agent.post { |value| 0 }
81
104
  end
82
105
  end
83
106
 
@@ -135,20 +158,54 @@ module Concurrent
135
158
  context '#post' do
136
159
 
137
160
  it 'adds the given block to the queue' do
138
- executor.should_receive(:post).with(no_args).exactly(3).times
139
- subject.post { sleep(100) }
161
+ executor.should_receive(:post).with(no_args).exactly(1).times
162
+ subject.post { sleep(1) }
140
163
  subject.post { nil }
141
164
  subject.post { nil }
142
165
  sleep(0.1)
166
+ subject.
167
+ instance_variable_get(:@one_by_one).
168
+ instance_variable_get(:@stash).
169
+ size.should eq 2
143
170
  end
144
171
 
145
172
  it 'does not add to the queue when no block is given' do
146
- executor.should_receive(:post).with(no_args).exactly(2).times
147
- subject.post { sleep(100) }
173
+ executor.should_receive(:post).with(no_args).exactly(0).times
148
174
  subject.post
149
- subject.post { nil }
150
175
  sleep(0.1)
151
176
  end
177
+
178
+ it 'works with ImmediateExecutor' do
179
+ agent = Agent.new(0, executor: ImmediateExecutor.new)
180
+ agent.post { |old| old + 1 }
181
+ agent.post { |old| old + 1 }
182
+ agent.value.should eq 2
183
+ end
184
+
185
+ end
186
+
187
+ context '#await' do
188
+
189
+ it 'waits until already sent updates are done' do
190
+ fn = false
191
+ subject.post { fn = true; sleep 0.1 }
192
+ subject.await
193
+ fn.should be_true
194
+ end
195
+
196
+ it 'does not waits until updates sent after are done' do
197
+ fn = false
198
+ subject.await
199
+ subject.post { fn = true; sleep 0.1 }
200
+ fn.should be_false
201
+ end
202
+
203
+ it 'does not alter the value' do
204
+ subject.post { |v| v + 1 }
205
+ subject.await
206
+ subject.value.should eq 1
207
+ end
208
+
152
209
  end
153
210
 
154
211
  context 'fulfillment' do
@@ -227,85 +284,85 @@ module Concurrent
227
284
  it 'calls the first exception block with a matching class' do
228
285
  @expected = nil
229
286
  subject.
230
- rescue(StandardError) { |ex| @expected = 1 }.
231
- rescue(StandardError) { |ex| @expected = 2 }.
232
- rescue(StandardError) { |ex| @expected = 3 }
233
- subject.post { raise StandardError }
234
- sleep(0.1)
235
- @expected.should eq 1
236
- end
287
+ rescue(StandardError) { |ex| @expected = 1 }.
288
+ rescue(StandardError) { |ex| @expected = 2 }.
289
+ rescue(StandardError) { |ex| @expected = 3 }
290
+ subject.post { raise StandardError }
291
+ sleep(0.1)
292
+ @expected.should eq 1
293
+ end
237
294
 
238
295
  it 'matches all with a rescue with no class given' do
239
296
  @expected = nil
240
297
  subject.
241
- rescue(LoadError) { |ex| @expected = 1 }.
242
- rescue { |ex| @expected = 2 }.
243
- rescue(StandardError) { |ex| @expected = 3 }
244
- subject.post { raise NoMethodError }
245
- sleep(0.1)
246
- @expected.should eq 2
247
- end
298
+ rescue(LoadError) { |ex| @expected = 1 }.
299
+ rescue { |ex| @expected = 2 }.
300
+ rescue(StandardError) { |ex| @expected = 3 }
301
+ subject.post { raise NoMethodError }
302
+ sleep(0.1)
303
+ @expected.should eq 2
304
+ end
248
305
 
249
306
  it 'searches associated rescue handlers in order' do
250
307
  @expected = nil
251
308
  subject.
252
- rescue(ArgumentError) { |ex| @expected = 1 }.
253
- rescue(LoadError) { |ex| @expected = 2 }.
254
- rescue(StandardError) { |ex| @expected = 3 }
255
- subject.post { raise ArgumentError }
256
- sleep(0.1)
257
- @expected.should eq 1
309
+ rescue(ArgumentError) { |ex| @expected = 1 }.
310
+ rescue(LoadError) { |ex| @expected = 2 }.
311
+ rescue(StandardError) { |ex| @expected = 3 }
312
+ subject.post { raise ArgumentError }
313
+ sleep(0.1)
314
+ @expected.should eq 1
258
315
 
259
- @expected = nil
260
- subject.
261
- rescue(ArgumentError) { |ex| @expected = 1 }.
262
- rescue(LoadError) { |ex| @expected = 2 }.
263
- rescue(StandardError) { |ex| @expected = 3 }
264
- subject.post { raise LoadError }
265
- sleep(0.1)
266
- @expected.should eq 2
267
-
268
- @expected = nil
269
- subject.
270
- rescue(ArgumentError) { |ex| @expected = 1 }.
316
+ @expected = nil
317
+ subject.
318
+ rescue(ArgumentError) { |ex| @expected = 1 }.
319
+ rescue(LoadError) { |ex| @expected = 2 }.
320
+ rescue(StandardError) { |ex| @expected = 3 }
321
+ subject.post { raise LoadError }
322
+ sleep(0.1)
323
+ @expected.should eq 2
324
+
325
+ @expected = nil
326
+ subject.
327
+ rescue(ArgumentError) { |ex| @expected = 1 }.
271
328
  rescue(LoadError) { |ex| @expected = 2 }.
272
329
  rescue(StandardError) { |ex| @expected = 3 }
273
- subject.post { raise StandardError }
274
- sleep(0.1)
275
- @expected.should eq 3
276
- end
330
+ subject.post { raise StandardError }
331
+ sleep(0.1)
332
+ @expected.should eq 3
333
+ end
277
334
 
278
335
  it 'passes the exception object to the matched block' do
279
336
  @expected = nil
280
337
  subject.
281
- rescue(ArgumentError) { |ex| @expected = ex }.
282
- rescue(LoadError) { |ex| @expected = ex }.
283
- rescue(StandardError) { |ex| @expected = ex }
284
- subject.post { raise StandardError }
285
- sleep(0.1)
286
- @expected.should be_a(StandardError)
287
- end
338
+ rescue(ArgumentError) { |ex| @expected = ex }.
339
+ rescue(LoadError) { |ex| @expected = ex }.
340
+ rescue(StandardError) { |ex| @expected = ex }
341
+ subject.post { raise StandardError }
342
+ sleep(0.1)
343
+ @expected.should be_a(StandardError)
344
+ end
288
345
 
289
346
  it 'ignores rescuers without a block' do
290
347
  @expected = nil
291
348
  subject.
292
- rescue(StandardError).
293
- rescue(StandardError) { |ex| @expected = ex }
294
- subject.post { raise StandardError }
295
- sleep(0.1)
296
- @expected.should be_a(StandardError)
297
- end
349
+ rescue(StandardError).
350
+ rescue(StandardError) { |ex| @expected = ex }
351
+ subject.post { raise StandardError }
352
+ sleep(0.1)
353
+ @expected.should be_a(StandardError)
354
+ end
298
355
 
299
356
  it 'supresses the exception if no rescue matches' do
300
357
  lambda {
301
358
  subject.
302
- rescue(ArgumentError) { |ex| @expected = ex }.
303
- rescue(NotImplementedError) { |ex| @expected = ex }.
304
- rescue(NoMethodError) { |ex| @expected = ex }
359
+ rescue(ArgumentError) { |ex| @expected = ex }.
360
+ rescue(NotImplementedError) { |ex| @expected = ex }.
361
+ rescue(NoMethodError) { |ex| @expected = ex }
305
362
  subject.post { raise StandardError }
306
363
  sleep(0.1)
307
364
  }.should_not raise_error
308
- end
365
+ end
309
366
 
310
367
  it 'suppresses exceptions thrown from rescue handlers' do
311
368
  lambda {
@@ -353,6 +410,46 @@ module Concurrent
353
410
  end
354
411
  end
355
412
 
413
+ context 'clojure-like behaviour' do
414
+ it 'does not block dereferencing when updating the value' do
415
+ continue = IVar.new
416
+ agent = Agent.new(0, executor: executor)
417
+ agent.post { |old| old + continue.value }
418
+ sleep 0.1
419
+ Concurrent.timeout(0.2) { agent.value.should eq 0 }
420
+ continue.set 1
421
+ sleep 0.1
422
+ end
423
+
424
+ it 'does not allow to execute two updates at the same time' do
425
+ agent = Agent.new(0, executor: executor)
426
+ continue1 = IVar.new
427
+ continue2 = IVar.new
428
+ f1 = f2 = false
429
+ agent.post { |old| f1 = true; old + continue1.value }
430
+ agent.post { |old| f2 = true; old + continue2.value }
431
+
432
+ sleep 0.1
433
+ f1.should eq true
434
+ f2.should eq false
435
+ agent.value.should eq 0
436
+
437
+ continue1.set 1
438
+ sleep 0.1
439
+ f1.should eq true
440
+ f2.should eq true
441
+ agent.value.should eq 1
442
+
443
+ continue2.set 1
444
+ sleep 0.1
445
+ f1.should eq true
446
+ f2.should eq true
447
+ agent.value.should eq 2
448
+ end
449
+
450
+ it 'waits with sending functions to other agents until update is done'
451
+ end
452
+
356
453
  context 'aliases' do
357
454
 
358
455
  it 'aliases #deref for #value' do
@@ -398,14 +495,6 @@ module Concurrent
398
495
  sleep(0.1)
399
496
  @expected.should be_true
400
497
  end
401
-
402
- it 'aliases #add_watch for #add_observer' do
403
- agent = Agent.new(0, executor: executor)
404
- agent.add_watch(observer)
405
- agent.post { 10 }
406
- sleep(0.1)
407
- observer.value.should eq 10
408
- end
409
498
  end
410
499
  end
411
500
  end
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+
3
+ share_examples_for :atomic_boolean do
4
+
5
+ describe 'construction' do
6
+
7
+ it 'sets the initial value' do
8
+ described_class.new(true).value.should be_true
9
+ end
10
+
11
+ it 'defaults the initial value to false' do
12
+ described_class.new.value.should be_false
13
+ end
14
+
15
+ it 'evaluates the truthiness of a true value' do
16
+ described_class.new(10).value.should be_true
17
+ end
18
+
19
+ it 'evaluates the truthiness of a false value' do
20
+ described_class.new(nil).value.should be_false
21
+ end
22
+ end
23
+
24
+ describe '#value' do
25
+
26
+ it 'returns the current value' do
27
+ counter = described_class.new(true)
28
+ counter.value.should be_true
29
+ counter.make_false
30
+ counter.value.should be_false
31
+ counter.make_true
32
+ counter.value.should be_true
33
+ end
34
+ end
35
+
36
+ describe '#value=' do
37
+
38
+ it 'sets the #value to the given `Boolean`' do
39
+ atomic = described_class.new(true)
40
+ atomic.value = false
41
+ atomic.value.should be_false
42
+ end
43
+
44
+ it 'returns the new value' do
45
+ atomic = described_class.new(false)
46
+ (atomic.value = true).should be_true
47
+ end
48
+
49
+ it 'evaluates the truthiness of a true value' do
50
+ atomic = described_class.new(false)
51
+ atomic.value = 10
52
+ atomic.value.should be_true
53
+ end
54
+
55
+ it 'evaluates the truthiness of a false value' do
56
+ atomic = described_class.new(true)
57
+ atomic.value = nil
58
+ atomic.value.should be_false
59
+ end
60
+ end
61
+
62
+ describe '#true?' do
63
+
64
+ specify { described_class.new(true).true?.should be_true }
65
+
66
+ specify { described_class.new(false).true?.should be_false }
67
+ end
68
+
69
+ describe '#false?' do
70
+
71
+ specify { described_class.new(true).false?.should be_false }
72
+
73
+ specify { described_class.new(false).false?.should be_true }
74
+ end
75
+
76
+ describe '#make_true' do
77
+
78
+ it 'makes a false value true and returns true' do
79
+ subject = described_class.new(false)
80
+ subject.make_true.should be_true
81
+ subject.value.should be_true
82
+ end
83
+
84
+ it 'keeps a true value true and returns false' do
85
+ subject = described_class.new(true)
86
+ subject.make_true.should be_false
87
+ subject.value.should be_true
88
+ end
89
+ end
90
+
91
+ describe '#make_false' do
92
+
93
+ it 'makes a true value false and returns true' do
94
+ subject = described_class.new(true)
95
+ subject.make_false.should be_true
96
+ subject.value.should be_false
97
+ end
98
+
99
+ it 'keeps a false value false and returns false' do
100
+ subject = described_class.new(false)
101
+ subject.make_false.should be_false
102
+ subject.value.should be_false
103
+ end
104
+ end
105
+ end
106
+
107
+ module Concurrent
108
+
109
+ describe MutexAtomicBoolean do
110
+
111
+ it_should_behave_like :atomic_boolean
112
+
113
+ specify 'construction is synchronized' do
114
+ mutex = double('mutex')
115
+ Mutex.should_receive(:new).once.with(no_args).and_return(mutex)
116
+ described_class.new
117
+ end
118
+
119
+ context 'instance methods' do
120
+
121
+ before(:each) do
122
+ mutex = double('mutex')
123
+ Mutex.stub(:new).with(no_args).and_return(mutex)
124
+ mutex.should_receive(:lock)
125
+ mutex.should_receive(:unlock)
126
+ end
127
+
128
+ specify 'value is synchronized' do
129
+ described_class.new.value
130
+ end
131
+
132
+ specify 'value= is synchronized' do
133
+ described_class.new.value = 10
134
+ end
135
+
136
+ specify 'true? is synchronized' do
137
+ described_class.new.true?
138
+ end
139
+
140
+ specify 'false? is synchronized' do
141
+ described_class.new.false?
142
+ end
143
+
144
+ specify 'make_true is synchronized' do
145
+ described_class.new.make_true
146
+ end
147
+
148
+ specify 'make_false is synchronized' do
149
+ described_class.new.make_false
150
+ end
151
+ end
152
+ end
153
+
154
+ if jruby?
155
+
156
+ describe JavaAtomicBoolean do
157
+ it_should_behave_like :atomic_boolean
158
+ end
159
+ end
160
+
161
+ describe AtomicBoolean do
162
+ if jruby?
163
+ it 'inherits from JavaAtomicBoolean' do
164
+ AtomicBoolean.ancestors.should include(JavaAtomicBoolean)
165
+ end
166
+ else
167
+ it 'inherits from MutexAtomicBoolean' do
168
+ AtomicBoolean.ancestors.should include(MutexAtomicBoolean)
169
+ end
170
+ end
171
+ end
172
+ end