o-concurrent-ruby 1.1.11

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 +7 -0
  2. data/CHANGELOG.md +542 -0
  3. data/Gemfile +37 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +404 -0
  6. data/Rakefile +307 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +189 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby/concurrent/agent.rb +587 -0
  23. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  24. data/lib/concurrent-ruby/concurrent/async.rb +449 -0
  25. data/lib/concurrent-ruby/concurrent/atom.rb +222 -0
  26. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +66 -0
  27. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +126 -0
  28. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +143 -0
  29. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  30. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +205 -0
  31. data/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb +100 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +128 -0
  33. data/lib/concurrent-ruby/concurrent/atomic/event.rb +109 -0
  34. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +42 -0
  35. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +37 -0
  36. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
  37. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
  38. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +44 -0
  39. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +131 -0
  40. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +254 -0
  41. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +377 -0
  42. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +181 -0
  43. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +166 -0
  44. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +104 -0
  45. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +56 -0
  46. data/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
  47. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  48. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
  49. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +111 -0
  50. data/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  51. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  52. data/lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  53. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +66 -0
  54. data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
  55. data/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb +82 -0
  56. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  57. data/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  58. data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +160 -0
  59. data/lib/concurrent-ruby/concurrent/concern/deprecation.rb +34 -0
  60. data/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb +73 -0
  61. data/lib/concurrent-ruby/concurrent/concern/logging.rb +32 -0
  62. data/lib/concurrent-ruby/concurrent/concern/obligation.rb +220 -0
  63. data/lib/concurrent-ruby/concurrent/concern/observable.rb +110 -0
  64. data/lib/concurrent-ruby/concurrent/configuration.rb +188 -0
  65. data/lib/concurrent-ruby/concurrent/constants.rb +8 -0
  66. data/lib/concurrent-ruby/concurrent/dataflow.rb +81 -0
  67. data/lib/concurrent-ruby/concurrent/delay.rb +199 -0
  68. data/lib/concurrent-ruby/concurrent/errors.rb +69 -0
  69. data/lib/concurrent-ruby/concurrent/exchanger.rb +352 -0
  70. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +131 -0
  71. data/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb +62 -0
  72. data/lib/concurrent-ruby/concurrent/executor/executor_service.rb +185 -0
  73. data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +220 -0
  74. data/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb +66 -0
  75. data/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb +44 -0
  76. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +103 -0
  77. data/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb +30 -0
  78. data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +140 -0
  79. data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +82 -0
  80. data/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb +21 -0
  81. data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +368 -0
  82. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +35 -0
  83. data/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb +34 -0
  84. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +107 -0
  85. data/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb +28 -0
  86. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +100 -0
  87. data/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb +57 -0
  88. data/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb +88 -0
  89. data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +172 -0
  90. data/lib/concurrent-ruby/concurrent/executors.rb +20 -0
  91. data/lib/concurrent-ruby/concurrent/future.rb +141 -0
  92. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  93. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +101 -0
  94. data/lib/concurrent-ruby/concurrent/ivar.rb +207 -0
  95. data/lib/concurrent-ruby/concurrent/map.rb +346 -0
  96. data/lib/concurrent-ruby/concurrent/maybe.rb +229 -0
  97. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +239 -0
  98. data/lib/concurrent-ruby/concurrent/mvar.rb +242 -0
  99. data/lib/concurrent-ruby/concurrent/options.rb +42 -0
  100. data/lib/concurrent-ruby/concurrent/promise.rb +580 -0
  101. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  102. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  103. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +331 -0
  104. data/lib/concurrent-ruby/concurrent/set.rb +74 -0
  105. data/lib/concurrent-ruby/concurrent/settable_struct.rb +139 -0
  106. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  107. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +24 -0
  108. data/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb +171 -0
  109. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +60 -0
  110. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  111. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +45 -0
  112. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +36 -0
  113. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +72 -0
  114. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +44 -0
  115. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +88 -0
  116. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +183 -0
  117. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +71 -0
  118. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +49 -0
  119. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  120. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +36 -0
  121. data/lib/concurrent-ruby/concurrent/synchronization.rb +30 -0
  122. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  123. data/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb +74 -0
  124. data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  125. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +88 -0
  126. data/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  127. data/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb +246 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb +75 -0
  129. data/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  130. data/lib/concurrent-ruby/concurrent/thread_safe/util.rb +16 -0
  131. data/lib/concurrent-ruby/concurrent/timer_task.rb +311 -0
  132. data/lib/concurrent-ruby/concurrent/tuple.rb +86 -0
  133. data/lib/concurrent-ruby/concurrent/tvar.rb +221 -0
  134. data/lib/concurrent-ruby/concurrent/utility/engine.rb +56 -0
  135. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
  136. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  137. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +53 -0
  138. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +130 -0
  139. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  140. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  141. data/lib/concurrent-ruby/concurrent.rb +134 -0
  142. metadata +192 -0
@@ -0,0 +1,100 @@
1
+ require 'concurrent/utility/engine'
2
+ require 'concurrent/atomic/mutex_count_down_latch'
3
+ require 'concurrent/atomic/java_count_down_latch'
4
+
5
+ module Concurrent
6
+
7
+ ###################################################################
8
+
9
+ # @!macro count_down_latch_method_initialize
10
+ #
11
+ # Create a new `CountDownLatch` with the initial `count`.
12
+ #
13
+ # @param [new] count the initial count
14
+ #
15
+ # @raise [ArgumentError] if `count` is not an integer or is less than zero
16
+
17
+ # @!macro count_down_latch_method_wait
18
+ #
19
+ # Block on the latch until the counter reaches zero or until `timeout` is reached.
20
+ #
21
+ # @param [Fixnum] timeout the number of seconds to wait for the counter or `nil`
22
+ # to block indefinitely
23
+ # @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
24
+
25
+ # @!macro count_down_latch_method_count_down
26
+ #
27
+ # Signal the latch to decrement the counter. Will signal all blocked threads when
28
+ # the `count` reaches zero.
29
+
30
+ # @!macro count_down_latch_method_count
31
+ #
32
+ # The current value of the counter.
33
+ #
34
+ # @return [Fixnum] the current value of the counter
35
+
36
+ ###################################################################
37
+
38
+ # @!macro count_down_latch_public_api
39
+ #
40
+ # @!method initialize(count = 1)
41
+ # @!macro count_down_latch_method_initialize
42
+ #
43
+ # @!method wait(timeout = nil)
44
+ # @!macro count_down_latch_method_wait
45
+ #
46
+ # @!method count_down
47
+ # @!macro count_down_latch_method_count_down
48
+ #
49
+ # @!method count
50
+ # @!macro count_down_latch_method_count
51
+
52
+ ###################################################################
53
+
54
+ # @!visibility private
55
+ # @!macro internal_implementation_note
56
+ CountDownLatchImplementation = case
57
+ when Concurrent.on_jruby?
58
+ JavaCountDownLatch
59
+ else
60
+ MutexCountDownLatch
61
+ end
62
+ private_constant :CountDownLatchImplementation
63
+
64
+ # @!macro count_down_latch
65
+ #
66
+ # A synchronization object that allows one thread to wait on multiple other threads.
67
+ # The thread that will wait creates a `CountDownLatch` and sets the initial value
68
+ # (normally equal to the number of other threads). The initiating thread passes the
69
+ # latch to the other threads then waits for the other threads by calling the `#wait`
70
+ # method. Each of the other threads calls `#count_down` when done with its work.
71
+ # When the latch counter reaches zero the waiting thread is unblocked and continues
72
+ # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
73
+ #
74
+ # @!macro count_down_latch_public_api
75
+ # @example Waiter and Decrementer
76
+ # latch = Concurrent::CountDownLatch.new(3)
77
+ #
78
+ # waiter = Thread.new do
79
+ # latch.wait()
80
+ # puts ("Waiter released")
81
+ # end
82
+ #
83
+ # decrementer = Thread.new do
84
+ # sleep(1)
85
+ # latch.count_down
86
+ # puts latch.count
87
+ #
88
+ # sleep(1)
89
+ # latch.count_down
90
+ # puts latch.count
91
+ #
92
+ # sleep(1)
93
+ # latch.count_down
94
+ # puts latch.count
95
+ # end
96
+ #
97
+ # [waiter, decrementer].each(&:join)
98
+ class CountDownLatch < CountDownLatchImplementation
99
+ end
100
+ end
@@ -0,0 +1,128 @@
1
+ require 'concurrent/synchronization'
2
+ require 'concurrent/utility/native_integer'
3
+
4
+ module Concurrent
5
+
6
+ # A synchronization aid that allows a set of threads to all wait for each
7
+ # other to reach a common barrier point.
8
+ # @example
9
+ # barrier = Concurrent::CyclicBarrier.new(3)
10
+ # jobs = Array.new(3) { |i| -> { sleep i; p done: i } }
11
+ # process = -> (i) do
12
+ # # waiting to start at the same time
13
+ # barrier.wait
14
+ # # execute job
15
+ # jobs[i].call
16
+ # # wait for others to finish
17
+ # barrier.wait
18
+ # end
19
+ # threads = 2.times.map do |i|
20
+ # Thread.new(i, &process)
21
+ # end
22
+ #
23
+ # # use main as well
24
+ # process.call 2
25
+ #
26
+ # # here we can be sure that all jobs are processed
27
+ class CyclicBarrier < Synchronization::LockableObject
28
+
29
+ # @!visibility private
30
+ Generation = Struct.new(:status)
31
+ private_constant :Generation
32
+
33
+ # Create a new `CyclicBarrier` that waits for `parties` threads
34
+ #
35
+ # @param [Fixnum] parties the number of parties
36
+ # @yield an optional block that will be executed that will be executed after
37
+ # the last thread arrives and before the others are released
38
+ #
39
+ # @raise [ArgumentError] if `parties` is not an integer or is less than zero
40
+ def initialize(parties, &block)
41
+ Utility::NativeInteger.ensure_integer_and_bounds parties
42
+ Utility::NativeInteger.ensure_positive_and_no_zero parties
43
+
44
+ super(&nil)
45
+ synchronize { ns_initialize parties, &block }
46
+ end
47
+
48
+ # @return [Fixnum] the number of threads needed to pass the barrier
49
+ def parties
50
+ synchronize { @parties }
51
+ end
52
+
53
+ # @return [Fixnum] the number of threads currently waiting on the barrier
54
+ def number_waiting
55
+ synchronize { @number_waiting }
56
+ end
57
+
58
+ # Blocks on the barrier until the number of waiting threads is equal to
59
+ # `parties` or until `timeout` is reached or `reset` is called
60
+ # If a block has been passed to the constructor, it will be executed once by
61
+ # the last arrived thread before releasing the others
62
+ # @param [Fixnum] timeout the number of seconds to wait for the counter or
63
+ # `nil` to block indefinitely
64
+ # @return [Boolean] `true` if the `count` reaches zero else false on
65
+ # `timeout` or on `reset` or if the barrier is broken
66
+ def wait(timeout = nil)
67
+ synchronize do
68
+
69
+ return false unless @generation.status == :waiting
70
+
71
+ @number_waiting += 1
72
+
73
+ if @number_waiting == @parties
74
+ @action.call if @action
75
+ ns_generation_done @generation, :fulfilled
76
+ true
77
+ else
78
+ generation = @generation
79
+ if ns_wait_until(timeout) { generation.status != :waiting }
80
+ generation.status == :fulfilled
81
+ else
82
+ ns_generation_done generation, :broken, false
83
+ false
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ # resets the barrier to its initial state
90
+ # If there is at least one waiting thread, it will be woken up, the `wait`
91
+ # method will return false and the barrier will be broken
92
+ # If the barrier is broken, this method restores it to the original state
93
+ #
94
+ # @return [nil]
95
+ def reset
96
+ synchronize { ns_generation_done @generation, :reset }
97
+ end
98
+
99
+ # A barrier can be broken when:
100
+ # - a thread called the `reset` method while at least one other thread was waiting
101
+ # - at least one thread timed out on `wait` method
102
+ #
103
+ # A broken barrier can be restored using `reset` it's safer to create a new one
104
+ # @return [Boolean] true if the barrier is broken otherwise false
105
+ def broken?
106
+ synchronize { @generation.status != :waiting }
107
+ end
108
+
109
+ protected
110
+
111
+ def ns_generation_done(generation, status, continue = true)
112
+ generation.status = status
113
+ ns_next_generation if continue
114
+ ns_broadcast
115
+ end
116
+
117
+ def ns_next_generation
118
+ @generation = Generation.new(:waiting)
119
+ @number_waiting = 0
120
+ end
121
+
122
+ def ns_initialize(parties, &block)
123
+ @parties = parties
124
+ @action = block
125
+ ns_next_generation
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,109 @@
1
+ require 'thread'
2
+ require 'concurrent/synchronization'
3
+
4
+ module Concurrent
5
+
6
+ # Old school kernel-style event reminiscent of Win32 programming in C++.
7
+ #
8
+ # When an `Event` is created it is in the `unset` state. Threads can choose to
9
+ # `#wait` on the event, blocking until released by another thread. When one
10
+ # thread wants to alert all blocking threads it calls the `#set` method which
11
+ # will then wake up all listeners. Once an `Event` has been set it remains set.
12
+ # New threads calling `#wait` will return immediately. An `Event` may be
13
+ # `#reset` at any time once it has been set.
14
+ #
15
+ # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
16
+ # @example
17
+ # event = Concurrent::Event.new
18
+ #
19
+ # t1 = Thread.new do
20
+ # puts "t1 is waiting"
21
+ # event.wait(1)
22
+ # puts "event occurred"
23
+ # end
24
+ #
25
+ # t2 = Thread.new do
26
+ # puts "t2 calling set"
27
+ # event.set
28
+ # end
29
+ #
30
+ # [t1, t2].each(&:join)
31
+ #
32
+ # # prints:
33
+ # # t1 is waiting
34
+ # # t2 calling set
35
+ # # event occurred
36
+ class Event < Synchronization::LockableObject
37
+
38
+ # Creates a new `Event` in the unset state. Threads calling `#wait` on the
39
+ # `Event` will block.
40
+ def initialize
41
+ super
42
+ synchronize { ns_initialize }
43
+ end
44
+
45
+ # Is the object in the set state?
46
+ #
47
+ # @return [Boolean] indicating whether or not the `Event` has been set
48
+ def set?
49
+ synchronize { @set }
50
+ end
51
+
52
+ # Trigger the event, setting the state to `set` and releasing all threads
53
+ # waiting on the event. Has no effect if the `Event` has already been set.
54
+ #
55
+ # @return [Boolean] should always return `true`
56
+ def set
57
+ synchronize { ns_set }
58
+ end
59
+
60
+ def try?
61
+ synchronize { @set ? false : ns_set }
62
+ end
63
+
64
+ # Reset a previously set event back to the `unset` state.
65
+ # Has no effect if the `Event` has not yet been set.
66
+ #
67
+ # @return [Boolean] should always return `true`
68
+ def reset
69
+ synchronize do
70
+ if @set
71
+ @set = false
72
+ @iteration +=1
73
+ end
74
+ true
75
+ end
76
+ end
77
+
78
+ # Wait a given number of seconds for the `Event` to be set by another
79
+ # thread. Will wait forever when no `timeout` value is given. Returns
80
+ # immediately if the `Event` has already been set.
81
+ #
82
+ # @return [Boolean] true if the `Event` was set before timeout else false
83
+ def wait(timeout = nil)
84
+ synchronize do
85
+ unless @set
86
+ iteration = @iteration
87
+ ns_wait_until(timeout) { iteration < @iteration || @set }
88
+ else
89
+ true
90
+ end
91
+ end
92
+ end
93
+
94
+ protected
95
+
96
+ def ns_set
97
+ unless @set
98
+ @set = true
99
+ ns_broadcast
100
+ end
101
+ true
102
+ end
103
+
104
+ def ns_initialize
105
+ @set = false
106
+ @iteration = 0
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,42 @@
1
+ if Concurrent.on_jruby?
2
+
3
+ module Concurrent
4
+
5
+ # @!macro count_down_latch
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class JavaCountDownLatch
9
+
10
+ # @!macro count_down_latch_method_initialize
11
+ def initialize(count = 1)
12
+ Utility::NativeInteger.ensure_integer_and_bounds(count)
13
+ Utility::NativeInteger.ensure_positive(count)
14
+ @latch = java.util.concurrent.CountDownLatch.new(count)
15
+ end
16
+
17
+ # @!macro count_down_latch_method_wait
18
+ def wait(timeout = nil)
19
+ result = nil
20
+ if timeout.nil?
21
+ Synchronization::JRuby.sleep_interruptibly { @latch.await }
22
+ result = true
23
+ else
24
+ Synchronization::JRuby.sleep_interruptibly do
25
+ result = @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
26
+ end
27
+ end
28
+ result
29
+ end
30
+
31
+ # @!macro count_down_latch_method_count_down
32
+ def count_down
33
+ @latch.countDown
34
+ end
35
+
36
+ # @!macro count_down_latch_method_count
37
+ def count
38
+ @latch.getCount
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ require 'concurrent/atomic/abstract_thread_local_var'
2
+
3
+ if Concurrent.on_jruby?
4
+
5
+ module Concurrent
6
+
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
9
+ class JavaThreadLocalVar < AbstractThreadLocalVar
10
+
11
+ # @!macro thread_local_var_method_get
12
+ def value
13
+ value = @var.get
14
+
15
+ if value.nil?
16
+ default
17
+ elsif value == NULL
18
+ nil
19
+ else
20
+ value
21
+ end
22
+ end
23
+
24
+ # @!macro thread_local_var_method_set
25
+ def value=(value)
26
+ @var.set(value)
27
+ end
28
+
29
+ protected
30
+
31
+ # @!visibility private
32
+ def allocate_storage
33
+ @var = java.lang.ThreadLocal.new
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,62 @@
1
+ require 'concurrent/synchronization'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro atomic_boolean
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class MutexAtomicBoolean < Synchronization::LockableObject
9
+
10
+ # @!macro atomic_boolean_method_initialize
11
+ def initialize(initial = false)
12
+ super()
13
+ synchronize { ns_initialize(initial) }
14
+ end
15
+
16
+ # @!macro atomic_boolean_method_value_get
17
+ def value
18
+ synchronize { @value }
19
+ end
20
+
21
+ # @!macro atomic_boolean_method_value_set
22
+ def value=(value)
23
+ synchronize { @value = !!value }
24
+ end
25
+
26
+ # @!macro atomic_boolean_method_true_question
27
+ def true?
28
+ synchronize { @value }
29
+ end
30
+
31
+ # @!macro atomic_boolean_method_false_question
32
+ def false?
33
+ synchronize { !@value }
34
+ end
35
+
36
+ # @!macro atomic_boolean_method_make_true
37
+ def make_true
38
+ synchronize { ns_make_value(true) }
39
+ end
40
+
41
+ # @!macro atomic_boolean_method_make_false
42
+ def make_false
43
+ synchronize { ns_make_value(false) }
44
+ end
45
+
46
+ protected
47
+
48
+ # @!visibility private
49
+ def ns_initialize(initial)
50
+ @value = !!initial
51
+ end
52
+
53
+ private
54
+
55
+ # @!visibility private
56
+ def ns_make_value(value)
57
+ old = @value
58
+ @value = value
59
+ old != @value
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,75 @@
1
+ require 'concurrent/synchronization'
2
+ require 'concurrent/utility/native_integer'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro atomic_fixnum
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
9
+ class MutexAtomicFixnum < Synchronization::LockableObject
10
+
11
+ # @!macro atomic_fixnum_method_initialize
12
+ def initialize(initial = 0)
13
+ super()
14
+ synchronize { ns_initialize(initial) }
15
+ end
16
+
17
+ # @!macro atomic_fixnum_method_value_get
18
+ def value
19
+ synchronize { @value }
20
+ end
21
+
22
+ # @!macro atomic_fixnum_method_value_set
23
+ def value=(value)
24
+ synchronize { ns_set(value) }
25
+ end
26
+
27
+ # @!macro atomic_fixnum_method_increment
28
+ def increment(delta = 1)
29
+ synchronize { ns_set(@value + delta.to_i) }
30
+ end
31
+
32
+ alias_method :up, :increment
33
+
34
+ # @!macro atomic_fixnum_method_decrement
35
+ def decrement(delta = 1)
36
+ synchronize { ns_set(@value - delta.to_i) }
37
+ end
38
+
39
+ alias_method :down, :decrement
40
+
41
+ # @!macro atomic_fixnum_method_compare_and_set
42
+ def compare_and_set(expect, update)
43
+ synchronize do
44
+ if @value == expect.to_i
45
+ @value = update.to_i
46
+ true
47
+ else
48
+ false
49
+ end
50
+ end
51
+ end
52
+
53
+ # @!macro atomic_fixnum_method_update
54
+ def update
55
+ synchronize do
56
+ @value = yield @value
57
+ end
58
+ end
59
+
60
+ protected
61
+
62
+ # @!visibility private
63
+ def ns_initialize(initial)
64
+ ns_set(initial)
65
+ end
66
+
67
+ private
68
+
69
+ # @!visibility private
70
+ def ns_set(value)
71
+ Utility::NativeInteger.ensure_integer_and_bounds value
72
+ @value = value
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,44 @@
1
+ require 'concurrent/synchronization'
2
+ require 'concurrent/utility/native_integer'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro count_down_latch
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
9
+ class MutexCountDownLatch < Synchronization::LockableObject
10
+
11
+ # @!macro count_down_latch_method_initialize
12
+ def initialize(count = 1)
13
+ Utility::NativeInteger.ensure_integer_and_bounds count
14
+ Utility::NativeInteger.ensure_positive count
15
+
16
+ super()
17
+ synchronize { ns_initialize count }
18
+ end
19
+
20
+ # @!macro count_down_latch_method_wait
21
+ def wait(timeout = nil)
22
+ synchronize { ns_wait_until(timeout) { @count == 0 } }
23
+ end
24
+
25
+ # @!macro count_down_latch_method_count_down
26
+ def count_down
27
+ synchronize do
28
+ @count -= 1 if @count > 0
29
+ ns_broadcast if @count == 0
30
+ end
31
+ end
32
+
33
+ # @!macro count_down_latch_method_count
34
+ def count
35
+ synchronize { @count }
36
+ end
37
+
38
+ protected
39
+
40
+ def ns_initialize(count)
41
+ @count = count
42
+ end
43
+ end
44
+ end