concurrent-ruby 0.8.0.pre2-java → 0.9.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -3
  3. data/README.md +111 -55
  4. data/lib/concurrent.rb +90 -14
  5. data/lib/concurrent/async.rb +143 -51
  6. data/lib/concurrent/atom.rb +131 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +34 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +27 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +234 -109
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +19 -7
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  46. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  47. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  48. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  49. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  50. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  51. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  52. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  53. data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
  54. data/lib/concurrent/executor/timer_set.rb +96 -84
  55. data/lib/concurrent/executors.rb +1 -1
  56. data/lib/concurrent/future.rb +71 -38
  57. data/lib/concurrent/immutable_struct.rb +89 -0
  58. data/lib/concurrent/ivar.rb +152 -60
  59. data/lib/concurrent/lazy_register.rb +40 -20
  60. data/lib/concurrent/maybe.rb +226 -0
  61. data/lib/concurrent/mutable_struct.rb +227 -0
  62. data/lib/concurrent/mvar.rb +44 -43
  63. data/lib/concurrent/promise.rb +229 -136
  64. data/lib/concurrent/scheduled_task.rb +341 -43
  65. data/lib/concurrent/settable_struct.rb +127 -0
  66. data/lib/concurrent/synchronization.rb +17 -0
  67. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  68. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  69. data/lib/concurrent/synchronization/condition.rb +53 -0
  70. data/lib/concurrent/synchronization/java_object.rb +34 -0
  71. data/lib/concurrent/synchronization/lock.rb +32 -0
  72. data/lib/concurrent/synchronization/monitor_object.rb +26 -0
  73. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  74. data/lib/concurrent/synchronization/object.rb +78 -0
  75. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  76. data/lib/concurrent/timer_task.rb +92 -103
  77. data/lib/concurrent/tvar.rb +42 -38
  78. data/lib/concurrent/utilities.rb +3 -1
  79. data/lib/concurrent/utility/at_exit.rb +97 -0
  80. data/lib/concurrent/utility/engine.rb +44 -0
  81. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  82. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  83. data/lib/concurrent/utility/processor_counter.rb +156 -0
  84. data/lib/concurrent/utility/timeout.rb +18 -14
  85. data/lib/concurrent/utility/timer.rb +11 -6
  86. data/lib/concurrent/version.rb +2 -1
  87. data/lib/concurrent_ruby.rb +1 -0
  88. data/lib/concurrent_ruby_ext.jar +0 -0
  89. metadata +46 -66
  90. data/lib/concurrent/actor.rb +0 -103
  91. data/lib/concurrent/actor/behaviour.rb +0 -70
  92. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  93. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  94. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  95. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  96. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  97. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  98. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  99. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  100. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  101. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  102. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  103. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  104. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  105. data/lib/concurrent/actor/context.rb +0 -154
  106. data/lib/concurrent/actor/core.rb +0 -217
  107. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  108. data/lib/concurrent/actor/envelope.rb +0 -41
  109. data/lib/concurrent/actor/errors.rb +0 -27
  110. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  111. data/lib/concurrent/actor/public_delegations.rb +0 -40
  112. data/lib/concurrent/actor/reference.rb +0 -81
  113. data/lib/concurrent/actor/root.rb +0 -37
  114. data/lib/concurrent/actor/type_check.rb +0 -48
  115. data/lib/concurrent/actor/utils.rb +0 -10
  116. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  117. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  118. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  119. data/lib/concurrent/actor/utils/pool.rb +0 -59
  120. data/lib/concurrent/actress.rb +0 -3
  121. data/lib/concurrent/agent.rb +0 -209
  122. data/lib/concurrent/atomic.rb +0 -92
  123. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  124. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  125. data/lib/concurrent/atomic/synchronization.rb +0 -51
  126. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  127. data/lib/concurrent/channel/channel.rb +0 -41
  128. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  129. data/lib/concurrent/channel/waitable_list.rb +0 -40
  130. data/lib/concurrent/channels.rb +0 -5
  131. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  132. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  133. data/lib/concurrent/collections.rb +0 -3
  134. data/lib/concurrent/dereferenceable.rb +0 -108
  135. data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
  136. data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
  137. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
  138. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
  139. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  140. data/lib/concurrent/logging.rb +0 -20
  141. data/lib/concurrent/obligation.rb +0 -171
  142. data/lib/concurrent/observable.rb +0 -73
  143. data/lib/concurrent/options_parser.rb +0 -48
  144. data/lib/concurrent/utility/processor_count.rb +0 -152
  145. data/lib/extension_helper.rb +0 -37
@@ -1,4 +1,5 @@
1
- require_relative '../../extension_helper'
1
+ require 'concurrent/utility/native_extension_loader'
2
+ require 'concurrent/synchronization'
2
3
 
3
4
  module Concurrent
4
5
 
@@ -21,7 +22,10 @@ module Concurrent
21
22
  # 4.520000 0.030000 4.550000 ( 1.187000)
22
23
  #
23
24
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
24
- class MutexAtomicFixnum
25
+ #
26
+ # @!visibility private
27
+ # @!macro internal_implementation_note
28
+ class MutexAtomicFixnum < Synchronization::Object
25
29
 
26
30
  # http://stackoverflow.com/questions/535721/ruby-max-integer
27
31
  MIN_VALUE = -(2**(0.size * 8 - 2))
@@ -31,12 +35,11 @@ module Concurrent
31
35
  #
32
36
  # Creates a new `AtomicFixnum` with the given initial value.
33
37
  #
34
- # @param [Fixnum] init the initial value
38
+ # @param [Fixnum] initial the initial value
35
39
  # @raise [ArgumentError] if the initial value is not a `Fixnum`
36
- def initialize(init = 0)
37
- raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
38
- @value = init
39
- @mutex = Mutex.new
40
+ def initialize(initial = 0)
41
+ super()
42
+ synchronize { ns_initialize(initial) }
40
43
  end
41
44
 
42
45
  # @!macro [attach] atomic_fixnum_method_value_get
@@ -45,10 +48,7 @@ module Concurrent
45
48
  #
46
49
  # @return [Fixnum] the current value
47
50
  def value
48
- @mutex.lock
49
- @value
50
- ensure
51
- @mutex.unlock
51
+ synchronize { @value }
52
52
  end
53
53
 
54
54
  # @!macro [attach] atomic_fixnum_method_value_set
@@ -61,11 +61,7 @@ module Concurrent
61
61
  #
62
62
  # @raise [ArgumentError] if the new value is not a `Fixnum`
63
63
  def value=(value)
64
- raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
65
- @mutex.lock
66
- @value = value
67
- ensure
68
- @mutex.unlock
64
+ synchronize { ns_set(value) }
69
65
  end
70
66
 
71
67
  # @!macro [attach] atomic_fixnum_method_increment
@@ -74,10 +70,7 @@ module Concurrent
74
70
  #
75
71
  # @return [Fixnum] the current value after incrementation
76
72
  def increment
77
- @mutex.lock
78
- @value += 1
79
- ensure
80
- @mutex.unlock
73
+ synchronize { ns_set(@value + 1) }
81
74
  end
82
75
 
83
76
  alias_method :up, :increment
@@ -88,115 +81,94 @@ module Concurrent
88
81
  #
89
82
  # @return [Fixnum] the current value after decrementation
90
83
  def decrement
91
- @mutex.lock
92
- @value -= 1
93
- ensure
94
- @mutex.unlock
84
+ synchronize { ns_set(@value -1) }
95
85
  end
96
86
 
97
87
  alias_method :down, :decrement
98
88
 
99
89
  # @!macro [attach] atomic_fixnum_method_compare_and_set
100
- #
90
+ #
101
91
  # Atomically sets the value to the given updated value if the current
102
92
  # value == the expected value.
103
93
  #
104
94
  # @param [Fixnum] expect the expected value
105
95
  # @param [Fixnum] update the new value
106
96
  #
107
- # @return [Boolean] true if the value was updated else false
97
+ # @return [Fixnum] true if the value was updated else false
108
98
  def compare_and_set(expect, update)
109
- @mutex.lock
110
- if @value == expect
111
- @value = update
112
- true
113
- else
114
- false
99
+ synchronize do
100
+ if @value == expect
101
+ @value = update
102
+ true
103
+ else
104
+ false
105
+ end
115
106
  end
116
- ensure
117
- @mutex.unlock
118
107
  end
119
- end
120
-
121
- if RUBY_PLATFORM == 'java'
122
-
123
- # @!macro atomic_fixnum
124
- class JavaAtomicFixnum
125
108
 
126
- MIN_VALUE = Java::JavaLang::Long::MIN_VALUE
127
- MAX_VALUE = Java::JavaLang::Long::MAX_VALUE
109
+ protected
128
110
 
129
- # @!macro atomic_fixnum_method_initialize
130
- def initialize(init = 0)
131
- raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
132
- @atomic = java.util.concurrent.atomic.AtomicLong.new(init)
133
- end
134
-
135
- # @!macro atomic_fixnum_method_value_get
136
- def value
137
- @atomic.get
138
- end
139
-
140
- # @!macro atomic_fixnum_method_value_set
141
- def value=(value)
142
- raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
143
- @atomic.set(value)
144
- end
145
-
146
- # @!macro atomic_fixnum_method_increment
147
- def increment
148
- @atomic.increment_and_get
149
- end
150
- alias_method :up, :increment
111
+ # @!visibility private
112
+ def ns_initialize(initial)
113
+ ns_set(initial)
114
+ end
151
115
 
152
- # @!macro atomic_fixnum_method_decrement
153
- def decrement
154
- @atomic.decrement_and_get
155
- end
156
- alias_method :down, :decrement
116
+ private
157
117
 
158
- # @!macro atomic_fixnum_method_compare_and_set
159
- def compare_and_set(expect, update)
160
- @atomic.compare_and_set(expect, update)
161
- end
118
+ # @!visibility private
119
+ def ns_set(value)
120
+ range_check!(value)
121
+ @value = value
162
122
  end
163
123
 
164
- # @!macro atomic_fixnum
165
- class AtomicFixnum < JavaAtomicFixnum
124
+ # @!visibility private
125
+ def range_check!(value)
126
+ if !value.is_a?(Fixnum)
127
+ raise ArgumentError.new('value value must be a Fixnum')
128
+ elsif value > MAX_VALUE
129
+ raise RangeError.new("#{value} is greater than the maximum value of #{MAX_VALUE}")
130
+ elsif value < MIN_VALUE
131
+ raise RangeError.new("#{value} is less than the maximum value of #{MIN_VALUE}")
132
+ else
133
+ value
134
+ end
166
135
  end
136
+ end
167
137
 
168
- elsif defined?(CAtomicFixnum)
169
-
170
- # @!macro atomic_fixnum
171
- class CAtomicFixnum
138
+ # @!visibility private
139
+ # @!macro internal_implementation_note
140
+ AtomicFixnumImplementation = case
141
+ when Concurrent.on_jruby?
142
+ JavaAtomicFixnum
143
+ when defined?(CAtomicFixnum)
144
+ CAtomicFixnum
145
+ else
146
+ MutexAtomicFixnum
147
+ end
148
+ private_constant :AtomicFixnumImplementation
149
+
150
+ # @!macro atomic_fixnum
151
+ #
152
+ # @see Concurrent::MutexAtomicFixnum
153
+ class AtomicFixnum < AtomicFixnumImplementation
172
154
 
173
- # @!method initialize
174
- # @!macro atomic_fixnum_method_initialize
155
+ # @!method initialize(initial = 0)
156
+ # @!macro atomic_fixnum_method_initialize
175
157
 
176
- # @!method value
177
- # @!macro atomic_fixnum_method_value_get
158
+ # @!method value
159
+ # @!macro atomic_fixnum_method_value_get
178
160
 
179
- # @!method value=
180
- # @!macro atomic_fixnum_method_value_set
161
+ # @!method value=(value)
162
+ # @!macro atomic_fixnum_method_value_set
181
163
 
182
- # @!method increment
183
- # @!macro atomic_fixnum_method_increment
164
+ # @!method increment
165
+ # @!macro atomic_fixnum_method_increment
184
166
 
185
- # @!method decrement
186
- # @!macro atomic_fixnum_method_decrement
167
+ # @!method decrement
168
+ # @!macro atomic_fixnum_method_decrement
187
169
 
188
- # @!method compare_and_set
189
- # @!macro atomic_fixnum_method_compare_and_set
190
- end
170
+ # @!method compare_and_set(expect, update)
171
+ # @!macro atomic_fixnum_method_compare_and_set
191
172
 
192
- # @!macro atomic_fixnum
193
- class AtomicFixnum < CAtomicFixnum
194
- end
195
-
196
- else
197
-
198
- # @!macro atomic_fixnum
199
- class AtomicFixnum < MutexAtomicFixnum
200
- end
201
173
  end
202
174
  end
@@ -0,0 +1,49 @@
1
+ require 'concurrent/utility/native_extension_loader'
2
+ require 'concurrent/utility/engine'
3
+ require 'concurrent/atomic_reference/concurrent_update_error'
4
+ require 'concurrent/atomic_reference/mutex_atomic'
5
+
6
+ begin
7
+ # force fallback impl with FORCE_ATOMIC_FALLBACK=1
8
+ if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
9
+ ruby_engine = 'mutex_atomic'
10
+ else
11
+ ruby_engine = Concurrent.ruby_engine
12
+ end
13
+
14
+ require "concurrent/atomic_reference/#{ruby_engine}"
15
+ rescue LoadError
16
+ #warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
17
+ end
18
+
19
+ if defined? Concurrent::JavaAtomicReference
20
+
21
+ # @!macro atomic_reference
22
+ class Concurrent::AtomicReference < Concurrent::JavaAtomicReference
23
+ end
24
+
25
+ elsif defined? Concurrent::RbxAtomicReference
26
+
27
+ # @!macro atomic_reference
28
+ class Concurrent::AtomicReference < Concurrent::RbxAtomicReference
29
+ end
30
+
31
+ elsif defined? Concurrent::CAtomicReference
32
+
33
+ # @!macro atomic_reference
34
+ class Concurrent::AtomicReference < Concurrent::CAtomicReference
35
+ end
36
+
37
+ else
38
+
39
+ # @!macro atomic_reference
40
+ class Concurrent::AtomicReference < Concurrent::MutexAtomicReference
41
+ end
42
+ end
43
+
44
+ module Concurrent
45
+
46
+ # @see Concurrent::AtomicReference
47
+ # @deprecated Use Concurrent::AtomicReference instead.
48
+ Atomic = AtomicReference
49
+ end
@@ -1,14 +1,21 @@
1
+ require 'concurrent/utility/monotonic_time'
2
+ require 'concurrent/concern/deprecation'
3
+
1
4
  module Concurrent
2
5
 
3
- # Condition is a better implementation of standard Ruby ConditionVariable.
4
- # The biggest difference is the wait return value: Condition#wait returns
5
- # Condition::Result which make possible to know if waiting thread has been woken up
6
- # by an another thread (using #signal or #broadcast) or due to timeout.
6
+ # Condition is a better implementation of standard Ruby ConditionVariable. The
7
+ # biggest difference is the wait return value: Condition#wait returns
8
+ # Condition::Result which make possible to know if waiting thread has been
9
+ # woken up by an another thread (using #signal or #broadcast) or due to
10
+ # timeout.
11
+ #
12
+ # Every #wait must be guarded by a locked Mutex or a ThreadError will be
13
+ # risen. Although it's not mandatory, it's recommended to call also #signal
14
+ # and #broadcast within the same mutex
7
15
  #
8
- # Every #wait must be guarded by a locked Mutex or a ThreadError will be risen.
9
- # Although it's not mandatory, it's recommended to call also #signal and #broadcast within
10
- # the same mutex
16
+ # @deprecated
11
17
  class Condition
18
+ include Concern::Deprecation
12
19
 
13
20
  class Result
14
21
  def initialize(remaining_time)
@@ -17,12 +24,14 @@ module Concurrent
17
24
 
18
25
  attr_reader :remaining_time
19
26
 
20
- # @return [Boolean] true if current thread has been waken up by a #signal or a #broadcast call, otherwise false
27
+ # @return [Boolean] true if current thread has been waken up by a #signal
28
+ # or a #broadcast call , otherwise false
21
29
  def woken_up?
22
30
  @remaining_time.nil? || @remaining_time > 0
23
31
  end
24
32
 
25
- # @return [Boolean] true if current thread has been waken up due to a timeout, otherwise false
33
+ # @return [Boolean] true if current thread has been waken up due to a
34
+ # timeout, otherwise false
26
35
  def timed_out?
27
36
  @remaining_time != nil && @remaining_time <= 0
28
37
  end
@@ -32,20 +41,23 @@ module Concurrent
32
41
  end
33
42
 
34
43
  def initialize
44
+ deprecated 'Will be replaced with Synchronization::Object in v1.0.'
35
45
  @condition = ConditionVariable.new
36
46
  end
37
47
 
38
48
  # @param [Mutex] mutex the locked mutex guarding the wait
39
49
  # @param [Object] timeout nil means no timeout
40
50
  # @return [Result]
51
+ #
52
+ # @!macro monotonic_clock_warning
41
53
  def wait(mutex, timeout = nil)
42
- start_time = Time.now.to_f
54
+ start_time = Concurrent.monotonic_time
43
55
  @condition.wait(mutex, timeout)
44
56
 
45
57
  if timeout.nil?
46
58
  Result.new(nil)
47
59
  else
48
- Result.new(start_time + timeout - Time.now.to_f)
60
+ Result.new(start_time + timeout - Concurrent.monotonic_time)
49
61
  end
50
62
  end
51
63
 
@@ -62,6 +74,5 @@ module Concurrent
62
74
  @condition.broadcast
63
75
  true
64
76
  end
65
-
66
77
  end
67
78
  end
@@ -1,4 +1,4 @@
1
- require 'concurrent/atomic/condition'
1
+ require 'concurrent/synchronization'
2
2
 
3
3
  module Concurrent
4
4
 
@@ -11,7 +11,10 @@ module Concurrent
11
11
  # method. Each of the other threads calls `#count_down` when done with its work.
12
12
  # When the latch counter reaches zero the waiting thread is unblocked and continues
13
13
  # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
14
- class MutexCountDownLatch
14
+ #
15
+ # @!visibility private
16
+ # @!macro internal_implementation_note
17
+ class PureCountDownLatch < Synchronization::Object
15
18
 
16
19
  # @!macro [attach] count_down_latch_method_initialize
17
20
  #
@@ -20,13 +23,12 @@ module Concurrent
20
23
  # @param [Fixnum] count the initial count
21
24
  #
22
25
  # @raise [ArgumentError] if `count` is not an integer or is less than zero
23
- def initialize(count)
26
+ def initialize(count = 1)
24
27
  unless count.is_a?(Fixnum) && count >= 0
25
28
  raise ArgumentError.new('count must be in integer greater than or equal zero')
26
29
  end
27
- @mutex = Mutex.new
28
- @condition = Condition.new
29
- @count = count
30
+ super()
31
+ synchronize { ns_initialize count }
30
32
  end
31
33
 
32
34
  # @!macro [attach] count_down_latch_method_wait
@@ -37,15 +39,7 @@ module Concurrent
37
39
  # to block indefinitely
38
40
  # @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
39
41
  def wait(timeout = nil)
40
- @mutex.synchronize do
41
-
42
- remaining = Condition::Result.new(timeout)
43
- while @count > 0 && remaining.can_wait?
44
- remaining = @condition.wait(@mutex, remaining.remaining_time)
45
- end
46
-
47
- @count == 0
48
- end
42
+ synchronize { ns_wait_until(timeout) { @count == 0 } }
49
43
  end
50
44
 
51
45
  # @!macro [attach] count_down_latch_method_count_down
@@ -53,9 +47,9 @@ module Concurrent
53
47
  # Signal the latch to decrement the counter. Will signal all blocked threads when
54
48
  # the `count` reaches zero.
55
49
  def count_down
56
- @mutex.synchronize do
50
+ synchronize do
57
51
  @count -= 1 if @count > 0
58
- @condition.broadcast if @count == 0
52
+ ns_broadcast if @count == 0
59
53
  end
60
54
  end
61
55
 
@@ -65,17 +59,25 @@ module Concurrent
65
59
  #
66
60
  # @return [Fixnum] the current value of the counter
67
61
  def count
68
- @mutex.synchronize { @count }
62
+ synchronize { @count }
63
+ end
64
+
65
+ protected
66
+
67
+ def ns_initialize(count)
68
+ @count = count
69
69
  end
70
70
  end
71
71
 
72
- if RUBY_PLATFORM == 'java'
72
+ if Concurrent.on_jruby?
73
73
 
74
74
  # @!macro count_down_latch
75
+ # @!visibility private
76
+ # @!macro internal_implementation_note
75
77
  class JavaCountDownLatch
76
78
 
77
79
  # @!macro count_down_latch_method_initialize
78
- def initialize(count)
80
+ def initialize(count = 1)
79
81
  unless count.is_a?(Fixnum) && count >= 0
80
82
  raise ArgumentError.new('count must be in integer greater than or equal zero')
81
83
  end
@@ -110,7 +112,7 @@ module Concurrent
110
112
  else
111
113
 
112
114
  # @!macro count_down_latch
113
- class CountDownLatch < MutexCountDownLatch
115
+ class CountDownLatch < PureCountDownLatch
114
116
  end
115
117
  end
116
118
  end