concurrent-ruby 0.9.2-java → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -1
- data/README.md +86 -120
- data/lib/concurrent.rb +14 -5
- data/lib/concurrent/agent.rb +587 -0
- data/lib/concurrent/array.rb +39 -0
- data/lib/concurrent/async.rb +296 -149
- data/lib/concurrent/atom.rb +135 -45
- data/lib/concurrent/atomic/abstract_thread_local_var.rb +38 -0
- data/lib/concurrent/atomic/atomic_boolean.rb +83 -118
- data/lib/concurrent/atomic/atomic_fixnum.rb +101 -163
- data/lib/concurrent/atomic/atomic_reference.rb +1 -8
- data/lib/concurrent/atomic/count_down_latch.rb +62 -103
- data/lib/concurrent/atomic/cyclic_barrier.rb +3 -1
- data/lib/concurrent/atomic/event.rb +1 -1
- data/lib/concurrent/atomic/java_count_down_latch.rb +39 -0
- data/lib/concurrent/atomic/java_thread_local_var.rb +50 -0
- data/lib/concurrent/atomic/mutex_atomic_boolean.rb +60 -0
- data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +91 -0
- data/lib/concurrent/atomic/mutex_count_down_latch.rb +43 -0
- data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
- data/lib/concurrent/atomic/read_write_lock.rb +5 -4
- data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
- data/lib/concurrent/atomic/ruby_thread_local_var.rb +172 -0
- data/lib/concurrent/atomic/semaphore.rb +84 -178
- data/lib/concurrent/atomic/thread_local_var.rb +65 -294
- data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
- data/lib/concurrent/atomic_reference/jruby.rb +1 -1
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +14 -8
- data/lib/concurrent/atomic_reference/ruby.rb +1 -1
- data/lib/concurrent/atomics.rb +7 -37
- data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
- data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
- data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
- data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
- data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
- data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +144 -0
- data/lib/concurrent/collection/map/synchronized_map_backend.rb +86 -0
- data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
- data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
- data/lib/concurrent/concern/dereferenceable.rb +9 -24
- data/lib/concurrent/concern/logging.rb +1 -1
- data/lib/concurrent/concern/obligation.rb +11 -20
- data/lib/concurrent/concern/observable.rb +38 -13
- data/lib/concurrent/configuration.rb +23 -152
- data/lib/concurrent/constants.rb +8 -0
- data/lib/concurrent/delay.rb +14 -12
- data/lib/concurrent/exchanger.rb +339 -41
- data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
- data/lib/concurrent/executor/executor_service.rb +23 -359
- data/lib/concurrent/executor/immediate_executor.rb +3 -2
- data/lib/concurrent/executor/java_executor_service.rb +100 -0
- data/lib/concurrent/executor/java_single_thread_executor.rb +3 -3
- data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -4
- data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -66
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +25 -22
- data/lib/concurrent/executor/safe_task_executor.rb +6 -7
- data/lib/concurrent/executor/serial_executor_service.rb +34 -0
- data/lib/concurrent/executor/serialized_execution.rb +10 -33
- data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
- data/lib/concurrent/executor/simple_executor_service.rb +1 -10
- data/lib/concurrent/executor/single_thread_executor.rb +20 -10
- data/lib/concurrent/executor/timer_set.rb +8 -10
- data/lib/concurrent/executors.rb +12 -2
- data/lib/concurrent/future.rb +6 -4
- data/lib/concurrent/hash.rb +35 -0
- data/lib/concurrent/immutable_struct.rb +5 -1
- data/lib/concurrent/ivar.rb +12 -16
- data/lib/concurrent/lazy_register.rb +11 -8
- data/lib/concurrent/map.rb +180 -0
- data/lib/concurrent/maybe.rb +6 -3
- data/lib/concurrent/mutable_struct.rb +7 -6
- data/lib/concurrent/mvar.rb +26 -2
- data/lib/concurrent/{executor/executor.rb → options.rb} +5 -29
- data/lib/concurrent/promise.rb +7 -5
- data/lib/concurrent/scheduled_task.rb +13 -71
- data/lib/concurrent/settable_struct.rb +5 -4
- data/lib/concurrent/synchronization.rb +15 -3
- data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
- data/lib/concurrent/synchronization/abstract_object.rb +7 -146
- data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
- data/lib/concurrent/synchronization/condition.rb +6 -4
- data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
- data/lib/concurrent/synchronization/jruby_object.rb +44 -0
- data/lib/concurrent/synchronization/lock.rb +3 -2
- data/lib/concurrent/synchronization/lockable_object.rb +72 -0
- data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
- data/lib/concurrent/synchronization/mri_object.rb +43 -0
- data/lib/concurrent/synchronization/object.rb +140 -73
- data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
- data/lib/concurrent/synchronization/rbx_object.rb +30 -73
- data/lib/concurrent/synchronization/volatile.rb +34 -0
- data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
- data/lib/concurrent/thread_safe/util.rb +14 -0
- data/lib/concurrent/thread_safe/util/adder.rb +74 -0
- data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +30 -0
- data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
- data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
- data/lib/concurrent/thread_safe/util/striped64.rb +241 -0
- data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
- data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
- data/lib/concurrent/timer_task.rb +3 -4
- data/lib/concurrent/tuple.rb +86 -0
- data/lib/concurrent/tvar.rb +5 -1
- data/lib/concurrent/utility/at_exit.rb +1 -1
- data/lib/concurrent/utility/engine.rb +4 -0
- data/lib/concurrent/utility/monotonic_time.rb +3 -4
- data/lib/concurrent/utility/native_extension_loader.rb +50 -30
- data/lib/concurrent/version.rb +2 -2
- data/lib/concurrent_ruby_ext.jar +0 -0
- metadata +47 -12
- data/lib/concurrent/atomic/condition.rb +0 -78
- data/lib/concurrent/collection/priority_queue.rb +0 -360
- data/lib/concurrent/synchronization/java_object.rb +0 -34
- data/lib/concurrent/synchronization/monitor_object.rb +0 -27
- data/lib/concurrent/synchronization/mutex_object.rb +0 -43
- data/lib/concurrent/utilities.rb +0 -5
- data/lib/concurrent/utility/timeout.rb +0 -39
- data/lib/concurrent/utility/timer.rb +0 -26
- data/lib/concurrent_ruby.rb +0 -2
@@ -1,12 +1,13 @@
|
|
1
|
+
require 'concurrent/constants'
|
1
2
|
require 'concurrent/errors'
|
3
|
+
require 'concurrent/configuration'
|
2
4
|
require 'concurrent/ivar'
|
3
5
|
require 'concurrent/collection/copy_on_notify_observer_set'
|
4
|
-
require 'concurrent/executor/executor'
|
5
6
|
require 'concurrent/utility/monotonic_time'
|
6
|
-
require 'concurrent/concern/deprecation'
|
7
7
|
|
8
8
|
module Concurrent
|
9
|
-
|
9
|
+
|
10
|
+
autoload :Options, 'concurrent/options'
|
10
11
|
|
11
12
|
# `ScheduledTask` is a close relative of `Concurrent::Future` but with one
|
12
13
|
# important difference: A `Future` is set to execute as soon as possible
|
@@ -161,24 +162,20 @@ module Concurrent
|
|
161
162
|
#
|
162
163
|
# @raise [ArgumentError] When no block is given
|
163
164
|
# @raise [ArgumentError] When given a time that is in the past
|
164
|
-
#
|
165
|
-
# @!macro [attach] deprecated_scheduling_by_clock_time
|
166
|
-
#
|
167
|
-
# @note Scheduling is now based on a monotonic clock. This makes the timer much
|
168
|
-
# more accurate, but only when scheduling based on a delay interval.
|
169
|
-
# Scheduling a task based on a clock time is deprecated. It will still work
|
170
|
-
# but will not be supported in the 1.0 release.
|
171
165
|
def initialize(delay, opts = {}, &task)
|
172
166
|
raise ArgumentError.new('no block given') unless block_given?
|
173
|
-
|
167
|
+
raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0
|
168
|
+
|
169
|
+
super(NULL, opts, &nil)
|
170
|
+
|
174
171
|
synchronize do
|
175
|
-
@delay = calculate_delay!(delay) # may raise exception
|
176
172
|
ns_set_state(:unscheduled)
|
177
173
|
@parent = opts.fetch(:timer_set, Concurrent.global_timer_set)
|
178
174
|
@args = get_arguments_from(opts)
|
175
|
+
@delay = delay.to_f
|
179
176
|
@task = task
|
180
177
|
@time = nil
|
181
|
-
@executor =
|
178
|
+
@executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
|
182
179
|
self.observers = Collection::CopyOnNotifyObserverSet.new
|
183
180
|
end
|
184
181
|
end
|
@@ -190,16 +187,6 @@ module Concurrent
|
|
190
187
|
synchronize { @delay }
|
191
188
|
end
|
192
189
|
|
193
|
-
# The `delay` value given at instanciation.
|
194
|
-
#
|
195
|
-
# @return [Float] the initial delay.
|
196
|
-
#
|
197
|
-
# @deprecated use {#initial_delay} instead
|
198
|
-
def delay
|
199
|
-
deprecated_method 'delay', 'initial_delay'
|
200
|
-
initial_delay
|
201
|
-
end
|
202
|
-
|
203
190
|
# The monotonic time at which the the task is scheduled to be executed.
|
204
191
|
#
|
205
192
|
# @return [Float] the schedule time or nil if `unscheduled`
|
@@ -228,16 +215,6 @@ module Concurrent
|
|
228
215
|
synchronize { ns_check_state?(:processing) }
|
229
216
|
end
|
230
217
|
|
231
|
-
# In the task execution in progress?
|
232
|
-
#
|
233
|
-
# @return [Boolean] true if the task is in the given state else false
|
234
|
-
#
|
235
|
-
# @deprecated Use {#processing?} instead.
|
236
|
-
def in_progress?
|
237
|
-
deprecated_method 'in_progress?', 'processing?'
|
238
|
-
processing?
|
239
|
-
end
|
240
|
-
|
241
218
|
# Cancel this task and prevent it from executing. A task can only be
|
242
219
|
# cancelled if it is pending or unscheduled.
|
243
220
|
#
|
@@ -253,17 +230,6 @@ module Concurrent
|
|
253
230
|
end
|
254
231
|
end
|
255
232
|
|
256
|
-
# Cancel this task and prevent it from executing. A task can only be
|
257
|
-
# cancelled if it is `:pending` or `:unscheduled`.
|
258
|
-
#
|
259
|
-
# @return [Boolean] true if successfully cancelled else false
|
260
|
-
#
|
261
|
-
# @deprecated Use {#cancel} instead.
|
262
|
-
def stop
|
263
|
-
deprecated_method 'stop', 'cancel'
|
264
|
-
cancel
|
265
|
-
end
|
266
|
-
|
267
233
|
# Reschedule the task using the original delay and the current time.
|
268
234
|
# A task can only be reset while it is `:pending`.
|
269
235
|
#
|
@@ -281,7 +247,9 @@ module Concurrent
|
|
281
247
|
#
|
282
248
|
# @raise [ArgumentError] When given a time that is in the past
|
283
249
|
def reschedule(delay)
|
284
|
-
|
250
|
+
delay = delay.to_f
|
251
|
+
raise ArgumentError.new('seconds must be greater than zero') if delay < 0.0
|
252
|
+
synchronize{ ns_reschedule(delay) }
|
285
253
|
end
|
286
254
|
|
287
255
|
# Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending`
|
@@ -306,8 +274,6 @@ module Concurrent
|
|
306
274
|
# @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state
|
307
275
|
#
|
308
276
|
# @raise [ArgumentError] if no block is given
|
309
|
-
#
|
310
|
-
# @!macro deprecated_scheduling_by_clock_time
|
311
277
|
def self.execute(delay, opts = {}, &task)
|
312
278
|
new(delay, opts, &task).execute
|
313
279
|
end
|
@@ -348,29 +314,5 @@ module Concurrent
|
|
348
314
|
return false unless ns_check_state?(:pending)
|
349
315
|
@parent.send(:remove_task, self) && ns_schedule(delay)
|
350
316
|
end
|
351
|
-
|
352
|
-
# Calculate the actual delay in seconds based on the given delay.
|
353
|
-
#
|
354
|
-
# @param [Float] delay the number of seconds to wait for before executing the task
|
355
|
-
#
|
356
|
-
# @return [Float] the number of seconds to delay
|
357
|
-
#
|
358
|
-
# @raise [ArgumentError] if the intended execution time is not in the future
|
359
|
-
# @raise [ArgumentError] if no block is given
|
360
|
-
#
|
361
|
-
# @!macro deprecated_scheduling_by_clock_time
|
362
|
-
#
|
363
|
-
# @!visibility private
|
364
|
-
def calculate_delay!(delay)
|
365
|
-
if delay.is_a?(Time)
|
366
|
-
deprecated 'Use an interval not a clock time; schedule is now based on a monotonic clock'
|
367
|
-
now = Time.now
|
368
|
-
raise ArgumentError.new('schedule time must be in the future') if delay <= now
|
369
|
-
delay.to_f - now.to_f
|
370
|
-
else
|
371
|
-
raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0
|
372
|
-
delay.to_f
|
373
|
-
end
|
374
|
-
end
|
375
317
|
end
|
376
318
|
end
|
@@ -74,8 +74,9 @@ module Concurrent
|
|
74
74
|
# @raise [Concurrent::ImmutabilityError] if the given member has already been set
|
75
75
|
def []=(member, value)
|
76
76
|
if member.is_a? Integer
|
77
|
-
|
78
|
-
|
77
|
+
length = synchronize { @values.length }
|
78
|
+
if member >= length
|
79
|
+
raise IndexError.new("offset #{member} too large for struct(size:#{length})")
|
79
80
|
end
|
80
81
|
synchronize do
|
81
82
|
unless @values[member].nil?
|
@@ -101,10 +102,10 @@ module Concurrent
|
|
101
102
|
FACTORY.define_struct(clazz_name, args, &block)
|
102
103
|
end
|
103
104
|
|
104
|
-
FACTORY = Class.new(Synchronization::
|
105
|
+
FACTORY = Class.new(Synchronization::LockableObject) do
|
105
106
|
def define_struct(name, members, &block)
|
106
107
|
synchronize do
|
107
|
-
clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::
|
108
|
+
clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block)
|
108
109
|
members.each_with_index do |member, index|
|
109
110
|
clazz.send(:define_method, member) do
|
110
111
|
synchronize { @values[index] }
|
@@ -1,16 +1,28 @@
|
|
1
1
|
require 'concurrent/utility/engine'
|
2
|
+
|
2
3
|
require 'concurrent/synchronization/abstract_object'
|
3
|
-
require 'concurrent/
|
4
|
-
|
5
|
-
|
4
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
5
|
+
Concurrent.load_native_extensions
|
6
|
+
|
7
|
+
require 'concurrent/synchronization/mri_object'
|
8
|
+
require 'concurrent/synchronization/jruby_object'
|
6
9
|
require 'concurrent/synchronization/rbx_object'
|
7
10
|
require 'concurrent/synchronization/object'
|
11
|
+
require 'concurrent/synchronization/volatile'
|
12
|
+
|
13
|
+
require 'concurrent/synchronization/abstract_lockable_object'
|
14
|
+
require 'concurrent/synchronization/mri_lockable_object'
|
15
|
+
require 'concurrent/synchronization/jruby_lockable_object'
|
16
|
+
require 'concurrent/synchronization/rbx_lockable_object'
|
17
|
+
|
18
|
+
require 'concurrent/synchronization/lockable_object'
|
8
19
|
|
9
20
|
require 'concurrent/synchronization/condition'
|
10
21
|
require 'concurrent/synchronization/lock'
|
11
22
|
|
12
23
|
module Concurrent
|
13
24
|
# {include:file:doc/synchronization.md}
|
25
|
+
# {include:file:doc/synchronization-notes.md}
|
14
26
|
module Synchronization
|
15
27
|
end
|
16
28
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Concurrent
|
2
|
+
module Synchronization
|
3
|
+
|
4
|
+
# @!visibility private
|
5
|
+
class AbstractLockableObject < Object
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
# @!macro [attach] synchronization_object_method_synchronize
|
10
|
+
#
|
11
|
+
# @yield runs the block synchronized against this object,
|
12
|
+
# equivalent of java's `synchronize(this) {}`
|
13
|
+
# @note can by made public in descendants if required by `public :synchronize`
|
14
|
+
def synchronize
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
# @!macro [attach] synchronization_object_method_ns_wait_until
|
19
|
+
#
|
20
|
+
# Wait until condition is met or timeout passes,
|
21
|
+
# protects against spurious wake-ups.
|
22
|
+
# @param [Numeric, nil] timeout in seconds, `nil` means no timeout
|
23
|
+
# @yield condition to be met
|
24
|
+
# @yieldreturn [true, false]
|
25
|
+
# @return [true, false] if condition met
|
26
|
+
# @note only to be used inside synchronized block
|
27
|
+
# @note to provide direct access to this method in a descendant add method
|
28
|
+
# ```
|
29
|
+
# def wait_until(timeout = nil, &condition)
|
30
|
+
# synchronize { ns_wait_until(timeout, &condition) }
|
31
|
+
# end
|
32
|
+
# ```
|
33
|
+
def ns_wait_until(timeout = nil, &condition)
|
34
|
+
if timeout
|
35
|
+
wait_until = Concurrent.monotonic_time + timeout
|
36
|
+
loop do
|
37
|
+
now = Concurrent.monotonic_time
|
38
|
+
condition_result = condition.call
|
39
|
+
return condition_result if now >= wait_until || condition_result
|
40
|
+
ns_wait wait_until - now
|
41
|
+
end
|
42
|
+
else
|
43
|
+
ns_wait timeout until condition.call
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @!macro [attach] synchronization_object_method_ns_wait
|
49
|
+
#
|
50
|
+
# Wait until another thread calls #signal or #broadcast,
|
51
|
+
# spurious wake-ups can happen.
|
52
|
+
#
|
53
|
+
# @param [Numeric, nil] timeout in seconds, `nil` means no timeout
|
54
|
+
# @return [self]
|
55
|
+
# @note only to be used inside synchronized block
|
56
|
+
# @note to provide direct access to this method in a descendant add method
|
57
|
+
# ```
|
58
|
+
# def wait(timeout = nil)
|
59
|
+
# synchronize { ns_wait(timeout) }
|
60
|
+
# end
|
61
|
+
# ```
|
62
|
+
def ns_wait(timeout = nil)
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
# @!macro [attach] synchronization_object_method_ns_signal
|
67
|
+
#
|
68
|
+
# Signal one waiting thread.
|
69
|
+
# @return [self]
|
70
|
+
# @note only to be used inside synchronized block
|
71
|
+
# @note to provide direct access to this method in a descendant add method
|
72
|
+
# ```
|
73
|
+
# def signal
|
74
|
+
# synchronize { ns_signal }
|
75
|
+
# end
|
76
|
+
# ```
|
77
|
+
def ns_signal
|
78
|
+
raise NotImplementedError
|
79
|
+
end
|
80
|
+
|
81
|
+
# @!macro [attach] synchronization_object_method_ns_broadcast
|
82
|
+
#
|
83
|
+
# Broadcast to all waiting threads.
|
84
|
+
# @return [self]
|
85
|
+
# @note only to be used inside synchronized block
|
86
|
+
# @note to provide direct access to this method in a descendant add method
|
87
|
+
# ```
|
88
|
+
# def broadcast
|
89
|
+
# synchronize { ns_broadcast }
|
90
|
+
# end
|
91
|
+
# ```
|
92
|
+
def ns_broadcast
|
93
|
+
raise NotImplementedError
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -1,162 +1,23 @@
|
|
1
1
|
module Concurrent
|
2
2
|
module Synchronization
|
3
3
|
|
4
|
-
# @!macro synchronization_object
|
5
4
|
# @!visibility private
|
5
|
+
# @!macro internal_implementation_note
|
6
6
|
class AbstractObject
|
7
7
|
|
8
|
-
#
|
9
|
-
|
10
|
-
# @abstract for helper ivar initialization if needed,
|
11
|
-
# otherwise it can be left empty. It has to call ns_initialize.
|
12
|
-
def initialize(*args, &block)
|
8
|
+
# @abstract has to be implemented based on Ruby runtime
|
9
|
+
def initialize
|
13
10
|
raise NotImplementedError
|
14
11
|
end
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
# @yield runs the block synchronized against this object,
|
21
|
-
# equivalent of java's `synchronize(this) {}`
|
22
|
-
# @note can by made public in descendants if required by `public :synchronize`
|
23
|
-
def synchronize
|
24
|
-
raise NotImplementedError
|
25
|
-
end
|
26
|
-
|
27
|
-
# @!macro [attach] synchronization_object_method_ns_initialize
|
28
|
-
#
|
29
|
-
# initialization of the object called inside synchronize block
|
30
|
-
# @note has to be called manually when required in children of this class
|
31
|
-
# @example
|
32
|
-
# class Child < Concurrent::Synchornization::Object
|
33
|
-
# def initialize(*args, &block)
|
34
|
-
# super(&nil)
|
35
|
-
# synchronize { ns_initialize(*args, &block) }
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# def ns_initialize(*args, &block)
|
39
|
-
# @args = args
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
def ns_initialize(*args, &block)
|
43
|
-
end
|
44
|
-
|
45
|
-
# @!macro [attach] synchronization_object_method_ns_wait_until
|
46
|
-
#
|
47
|
-
# Wait until condition is met or timeout passes,
|
48
|
-
# protects against spurious wake-ups.
|
49
|
-
# @param [Numeric, nil] timeout in seconds, `nil` means no timeout
|
50
|
-
# @yield condition to be met
|
51
|
-
# @yieldreturn [true, false]
|
52
|
-
# @return [true, false] if condition met
|
53
|
-
# @note only to be used inside synchronized block
|
54
|
-
# @note to provide direct access to this method in a descendant add method
|
55
|
-
# ```
|
56
|
-
# def wait_until(timeout = nil, &condition)
|
57
|
-
# synchronize { ns_wait_until(timeout, &condition) }
|
58
|
-
# end
|
59
|
-
# ```
|
60
|
-
def ns_wait_until(timeout = nil, &condition)
|
61
|
-
if timeout
|
62
|
-
wait_until = Concurrent.monotonic_time + timeout
|
63
|
-
loop do
|
64
|
-
now = Concurrent.monotonic_time
|
65
|
-
condition_result = condition.call
|
66
|
-
# 0.001 correction to avoid error when `wait_until - now` is smaller than 0.0005 and rounded to 0
|
67
|
-
# when passed to java #wait(long timeout)
|
68
|
-
return condition_result if (now + 0.001) >= wait_until || condition_result
|
69
|
-
ns_wait wait_until - now
|
70
|
-
end
|
71
|
-
else
|
72
|
-
ns_wait timeout until condition.call
|
73
|
-
true
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# @!macro [attach] synchronization_object_method_ns_wait
|
78
|
-
#
|
79
|
-
# Wait until another thread calls #signal or #broadcast,
|
80
|
-
# spurious wake-ups can happen.
|
81
|
-
#
|
82
|
-
# @param [Numeric, nil] timeout in seconds, `nil` means no timeout
|
83
|
-
# @return [self]
|
84
|
-
# @note only to be used inside synchronized block
|
85
|
-
# @note to provide direct access to this method in a descendant add method
|
86
|
-
# ```
|
87
|
-
# def wait(timeout = nil)
|
88
|
-
# synchronize { ns_wait(timeout) }
|
89
|
-
# end
|
90
|
-
# ```
|
91
|
-
def ns_wait(timeout = nil)
|
13
|
+
# @!visibility private
|
14
|
+
# @abstract
|
15
|
+
def full_memory_barrier
|
92
16
|
raise NotImplementedError
|
93
17
|
end
|
94
18
|
|
95
|
-
# @!macro [attach] synchronization_object_method_ns_signal
|
96
|
-
#
|
97
|
-
# Signal one waiting thread.
|
98
|
-
# @return [self]
|
99
|
-
# @note only to be used inside synchronized block
|
100
|
-
# @note to provide direct access to this method in a descendant add method
|
101
|
-
# ```
|
102
|
-
# def signal
|
103
|
-
# synchronize { ns_signal }
|
104
|
-
# end
|
105
|
-
# ```
|
106
|
-
def ns_signal
|
107
|
-
raise NotImplementedError
|
108
|
-
end
|
109
|
-
|
110
|
-
# @!macro [attach] synchronization_object_method_ns_broadcast
|
111
|
-
#
|
112
|
-
# Broadcast to all waiting threads.
|
113
|
-
# @return [self]
|
114
|
-
# @note only to be used inside synchronized block
|
115
|
-
# @note to provide direct access to this method in a descendant add method
|
116
|
-
# ```
|
117
|
-
# def broadcast
|
118
|
-
# synchronize { ns_broadcast }
|
119
|
-
# end
|
120
|
-
# ```
|
121
|
-
def ns_broadcast
|
122
|
-
raise NotImplementedError
|
123
|
-
end
|
124
|
-
|
125
|
-
# @!macro [attach] synchronization_object_method_ensure_ivar_visibility
|
126
|
-
#
|
127
|
-
# Allows to construct immutable objects where all fields are visible after initialization, not requiring
|
128
|
-
# further synchronization on access.
|
129
|
-
# @example
|
130
|
-
# class AClass
|
131
|
-
# attr_reader :val
|
132
|
-
# def initialize(val)
|
133
|
-
# @val = val # final value, after assignment it's not changed (just convention, not enforced)
|
134
|
-
# ensure_ivar_visibility!
|
135
|
-
# # now it can be shared as Java's final field
|
136
|
-
# end
|
137
|
-
# end
|
138
|
-
def ensure_ivar_visibility!
|
139
|
-
raise NotImplementedError
|
140
|
-
end
|
141
|
-
|
142
|
-
# @!macro [attach] synchronization_object_method_self_attr_volatile
|
143
|
-
#
|
144
|
-
# creates methods for reading and writing to a instance variable with volatile (Java semantic) instance variable
|
145
|
-
# return [Array<Symbol>] names of defined method names
|
146
19
|
def self.attr_volatile(*names)
|
147
|
-
|
148
|
-
ivar = :"@volatile_#{name}"
|
149
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
150
|
-
def #{name}
|
151
|
-
#{ivar}
|
152
|
-
end
|
153
|
-
|
154
|
-
def #{name}=(value)
|
155
|
-
#{ivar} = value
|
156
|
-
end
|
157
|
-
RUBY
|
158
|
-
end
|
159
|
-
names.map { |n| [n, :"#{n}="] }.flatten
|
20
|
+
raise NotImplementedError
|
160
21
|
end
|
161
22
|
end
|
162
23
|
end
|