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

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 (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