concurrent-ruby 1.1.10 → 1.2.2
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 +20 -1
- data/Gemfile +0 -1
- data/README.md +21 -20
- data/Rakefile +53 -63
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
- data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
- data/lib/concurrent-ruby/concurrent/array.rb +0 -10
- data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +81 -151
- data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
- data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
- data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
- data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +5 -3
- data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
- data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
- data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
- data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
- data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +2 -2
- data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +16 -8
- data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
- data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
- data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
- data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +2 -2
- data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
- data/lib/concurrent-ruby/concurrent/hash.rb +0 -9
- data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
- data/lib/concurrent-ruby/concurrent/map.rb +43 -39
- data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
- data/lib/concurrent-ruby/concurrent/promise.rb +1 -1
- data/lib/concurrent-ruby/concurrent/promises.rb +7 -6
- data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
- data/lib/concurrent-ruby/concurrent/scheduled_task.rb +1 -1
- data/lib/concurrent-ruby/concurrent/set.rb +0 -10
- data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
- data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
- data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
- data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
- data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
- data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
- data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
- data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +2 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
- data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
- data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
- data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
- data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +34 -54
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- metadata +13 -15
- data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
- data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
- data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
- data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
@@ -1,102 +1,19 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/delay'
|
3
3
|
require 'concurrent/errors'
|
4
|
-
require 'concurrent/atomic/atomic_reference'
|
5
|
-
require 'concurrent/concern/logging'
|
6
4
|
require 'concurrent/concern/deprecation'
|
7
5
|
require 'concurrent/executor/immediate_executor'
|
6
|
+
require 'concurrent/executor/fixed_thread_pool'
|
8
7
|
require 'concurrent/executor/cached_thread_pool'
|
9
8
|
require 'concurrent/utility/processor_counter'
|
10
9
|
|
11
10
|
module Concurrent
|
12
|
-
extend Concern::Logging
|
13
11
|
extend Concern::Deprecation
|
14
12
|
|
15
13
|
autoload :Options, 'concurrent/options'
|
16
14
|
autoload :TimerSet, 'concurrent/executor/timer_set'
|
17
15
|
autoload :ThreadPoolExecutor, 'concurrent/executor/thread_pool_executor'
|
18
16
|
|
19
|
-
# @return [Logger] Logger with provided level and output.
|
20
|
-
def self.create_simple_logger(level = Logger::FATAL, output = $stderr)
|
21
|
-
# TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking
|
22
|
-
lambda do |severity, progname, message = nil, &block|
|
23
|
-
return false if severity < level
|
24
|
-
|
25
|
-
message = block ? block.call : message
|
26
|
-
formatted_message = case message
|
27
|
-
when String
|
28
|
-
message
|
29
|
-
when Exception
|
30
|
-
format "%s (%s)\n%s",
|
31
|
-
message.message, message.class, (message.backtrace || []).join("\n")
|
32
|
-
else
|
33
|
-
message.inspect
|
34
|
-
end
|
35
|
-
|
36
|
-
output.print format "[%s] %5s -- %s: %s\n",
|
37
|
-
Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'),
|
38
|
-
Logger::SEV_LABEL[severity],
|
39
|
-
progname,
|
40
|
-
formatted_message
|
41
|
-
true
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Use logger created by #create_simple_logger to log concurrent-ruby messages.
|
46
|
-
def self.use_simple_logger(level = Logger::FATAL, output = $stderr)
|
47
|
-
Concurrent.global_logger = create_simple_logger level, output
|
48
|
-
end
|
49
|
-
|
50
|
-
# @return [Logger] Logger with provided level and output.
|
51
|
-
# @deprecated
|
52
|
-
def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr)
|
53
|
-
logger = Logger.new(output)
|
54
|
-
logger.level = level
|
55
|
-
logger.formatter = lambda do |severity, datetime, progname, msg|
|
56
|
-
formatted_message = case msg
|
57
|
-
when String
|
58
|
-
msg
|
59
|
-
when Exception
|
60
|
-
format "%s (%s)\n%s",
|
61
|
-
msg.message, msg.class, (msg.backtrace || []).join("\n")
|
62
|
-
else
|
63
|
-
msg.inspect
|
64
|
-
end
|
65
|
-
format "[%s] %5s -- %s: %s\n",
|
66
|
-
datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
|
67
|
-
severity,
|
68
|
-
progname,
|
69
|
-
formatted_message
|
70
|
-
end
|
71
|
-
|
72
|
-
lambda do |loglevel, progname, message = nil, &block|
|
73
|
-
logger.add loglevel, message, progname, &block
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Use logger created by #create_stdlib_logger to log concurrent-ruby messages.
|
78
|
-
# @deprecated
|
79
|
-
def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr)
|
80
|
-
Concurrent.global_logger = create_stdlib_logger level, output
|
81
|
-
end
|
82
|
-
|
83
|
-
# TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods
|
84
|
-
|
85
|
-
# Suppresses all output when used for logging.
|
86
|
-
NULL_LOGGER = lambda { |level, progname, message = nil, &block| }
|
87
|
-
|
88
|
-
# @!visibility private
|
89
|
-
GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN))
|
90
|
-
private_constant :GLOBAL_LOGGER
|
91
|
-
|
92
|
-
def self.global_logger
|
93
|
-
GLOBAL_LOGGER.value
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.global_logger=(value)
|
97
|
-
GLOBAL_LOGGER.value = value
|
98
|
-
end
|
99
|
-
|
100
17
|
# @!visibility private
|
101
18
|
GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
|
102
19
|
private_constant :GLOBAL_FAST_EXECUTOR
|
@@ -136,14 +53,14 @@ module Concurrent
|
|
136
53
|
#
|
137
54
|
# @return [ThreadPoolExecutor] the thread pool
|
138
55
|
def self.global_fast_executor
|
139
|
-
GLOBAL_FAST_EXECUTOR.value
|
56
|
+
GLOBAL_FAST_EXECUTOR.value!
|
140
57
|
end
|
141
58
|
|
142
59
|
# Global thread pool optimized for long, blocking (IO) *tasks*.
|
143
60
|
#
|
144
61
|
# @return [ThreadPoolExecutor] the thread pool
|
145
62
|
def self.global_io_executor
|
146
|
-
GLOBAL_IO_EXECUTOR.value
|
63
|
+
GLOBAL_IO_EXECUTOR.value!
|
147
64
|
end
|
148
65
|
|
149
66
|
def self.global_immediate_executor
|
@@ -154,7 +71,7 @@ module Concurrent
|
|
154
71
|
#
|
155
72
|
# @return [Concurrent::TimerSet] the thread pool
|
156
73
|
def self.global_timer_set
|
157
|
-
GLOBAL_TIMER_SET.value
|
74
|
+
GLOBAL_TIMER_SET.value!
|
158
75
|
end
|
159
76
|
|
160
77
|
# General access point to global executors.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/concern/obligation'
|
3
3
|
require 'concurrent/executor/immediate_executor'
|
4
|
-
require 'concurrent/synchronization'
|
4
|
+
require 'concurrent/synchronization/lockable_object'
|
5
5
|
|
6
6
|
module Concurrent
|
7
7
|
|
@@ -67,7 +67,7 @@ module Concurrent
|
|
67
67
|
|
68
68
|
# Return the value this object represents after applying the options
|
69
69
|
# specified by the `#set_deref_options` method. If the delayed operation
|
70
|
-
# raised an exception this method will return nil. The
|
70
|
+
# raised an exception this method will return nil. The exception object
|
71
71
|
# can be accessed via the `#reason` method.
|
72
72
|
#
|
73
73
|
# @param [Numeric] timeout the maximum number of seconds to wait
|
@@ -66,4 +66,9 @@ module Concurrent
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
# @!macro internal_implementation_note
|
70
|
+
class ConcurrentUpdateError < ThreadError
|
71
|
+
# frozen pre-allocated backtrace to speed ConcurrentUpdateError
|
72
|
+
CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
|
73
|
+
end
|
69
74
|
end
|
@@ -1,5 +1,8 @@
|
|
1
|
-
require 'concurrent/
|
1
|
+
require 'concurrent/atomic/atomic_boolean'
|
2
|
+
require 'concurrent/atomic/atomic_fixnum'
|
3
|
+
require 'concurrent/atomic/event'
|
2
4
|
require 'concurrent/executor/executor_service'
|
5
|
+
require 'concurrent/executor/ruby_executor_service'
|
3
6
|
|
4
7
|
module Concurrent
|
5
8
|
|
@@ -28,15 +28,6 @@ module Concurrent
|
|
28
28
|
end
|
29
29
|
JRubyHash
|
30
30
|
|
31
|
-
when Concurrent.on_rbx?
|
32
|
-
require 'monitor'
|
33
|
-
require 'concurrent/thread_safe/util/data_structures'
|
34
|
-
|
35
|
-
class RbxHash < ::Hash
|
36
|
-
end
|
37
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxHash
|
38
|
-
RbxHash
|
39
|
-
|
40
31
|
when Concurrent.on_truffleruby?
|
41
32
|
require 'concurrent/thread_safe/util/data_structures'
|
42
33
|
|
@@ -3,7 +3,8 @@ require 'concurrent/errors'
|
|
3
3
|
require 'concurrent/collection/copy_on_write_observer_set'
|
4
4
|
require 'concurrent/concern/obligation'
|
5
5
|
require 'concurrent/concern/observable'
|
6
|
-
require 'concurrent/
|
6
|
+
require 'concurrent/executor/safe_task_executor'
|
7
|
+
require 'concurrent/synchronization/lockable_object'
|
7
8
|
|
8
9
|
module Concurrent
|
9
10
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/constants'
|
3
|
-
require 'concurrent/synchronization'
|
4
3
|
require 'concurrent/utility/engine'
|
5
4
|
|
6
5
|
module Concurrent
|
@@ -10,17 +9,20 @@ module Concurrent
|
|
10
9
|
# @!visibility private
|
11
10
|
MapImplementation = case
|
12
11
|
when Concurrent.on_jruby?
|
12
|
+
require 'concurrent/utility/native_extension_loader'
|
13
13
|
# noinspection RubyResolve
|
14
14
|
JRubyMapBackend
|
15
15
|
when Concurrent.on_cruby?
|
16
16
|
require 'concurrent/collection/map/mri_map_backend'
|
17
17
|
MriMapBackend
|
18
|
-
when Concurrent.on_truffleruby?
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
when Concurrent.on_truffleruby?
|
19
|
+
if defined?(::TruffleRuby::ConcurrentMap)
|
20
|
+
require 'concurrent/collection/map/truffleruby_map_backend'
|
21
|
+
TruffleRubyMapBackend
|
22
|
+
else
|
23
|
+
require 'concurrent/collection/map/atomic_reference_map_backend'
|
24
|
+
AtomicReferenceMapBackend
|
25
|
+
end
|
24
26
|
else
|
25
27
|
warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation'
|
26
28
|
require 'concurrent/collection/map/synchronized_map_backend'
|
@@ -44,6 +46,12 @@ module Concurrent
|
|
44
46
|
# @note Atomic methods taking a block do not allow the `self` instance
|
45
47
|
# to be used within the block. Doing so will cause a deadlock.
|
46
48
|
|
49
|
+
# @!method []=(key, value)
|
50
|
+
# Set a value with key
|
51
|
+
# @param [Object] key
|
52
|
+
# @param [Object] value
|
53
|
+
# @return [Object] the new value
|
54
|
+
|
47
55
|
# @!method compute_if_absent(key)
|
48
56
|
# Compute and store new value for key if the key is absent.
|
49
57
|
# @param [Object] key
|
@@ -117,41 +125,38 @@ module Concurrent
|
|
117
125
|
# @return [true, false] true if deleted
|
118
126
|
# @!macro map.atomic_method
|
119
127
|
|
120
|
-
#
|
121
|
-
|
122
|
-
if options.kind_of?(::Hash)
|
123
|
-
validate_options_hash!(options)
|
124
|
-
else
|
125
|
-
options = nil
|
126
|
-
end
|
128
|
+
# NonConcurrentMapBackend handles default_proc natively
|
129
|
+
unless defined?(Collection::NonConcurrentMapBackend) and self < Collection::NonConcurrentMapBackend
|
127
130
|
|
128
|
-
|
129
|
-
@default_proc
|
130
|
-
|
131
|
+
# @param [Hash, nil] options options to set the :initial_capacity or :load_factor. Ignored on some Rubies.
|
132
|
+
# @param [Proc] default_proc Optional block to compute the default value if the key is not set, like `Hash#default_proc`
|
133
|
+
def initialize(options = nil, &default_proc)
|
134
|
+
if options.kind_of?(::Hash)
|
135
|
+
validate_options_hash!(options)
|
136
|
+
else
|
137
|
+
options = nil
|
138
|
+
end
|
131
139
|
|
132
|
-
|
133
|
-
|
134
|
-
# @return [Object] the value
|
135
|
-
def [](key)
|
136
|
-
if value = super # non-falsy value is an existing mapping, return it right away
|
137
|
-
value
|
138
|
-
# re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
|
139
|
-
# a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
|
140
|
-
# would be returned)
|
141
|
-
# note: nil == value check is not technically necessary
|
142
|
-
elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
|
143
|
-
@default_proc.call(self, key)
|
144
|
-
else
|
145
|
-
value
|
140
|
+
super(options)
|
141
|
+
@default_proc = default_proc
|
146
142
|
end
|
147
|
-
end
|
148
143
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
144
|
+
# Get a value with key
|
145
|
+
# @param [Object] key
|
146
|
+
# @return [Object] the value
|
147
|
+
def [](key)
|
148
|
+
if value = super # non-falsy value is an existing mapping, return it right away
|
149
|
+
value
|
150
|
+
# re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
|
151
|
+
# a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
|
152
|
+
# would be returned)
|
153
|
+
# note: nil == value check is not technically necessary
|
154
|
+
elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
|
155
|
+
@default_proc.call(self, key)
|
156
|
+
else
|
157
|
+
value
|
158
|
+
end
|
159
|
+
end
|
155
160
|
end
|
156
161
|
|
157
162
|
alias_method :get, :[]
|
@@ -197,7 +202,6 @@ module Concurrent
|
|
197
202
|
# @yieldparam key [Object]
|
198
203
|
# @yieldreturn [Object] default value
|
199
204
|
# @return [Object] the value or default value
|
200
|
-
# @!macro map.atomic_method_with_block
|
201
205
|
def fetch_or_store(key, default_value = NULL)
|
202
206
|
fetch(key) do
|
203
207
|
put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
1
|
+
require 'concurrent/synchronization/object'
|
2
2
|
require 'concurrent/atomic/atomic_boolean'
|
3
3
|
require 'concurrent/atomic/atomic_fixnum'
|
4
4
|
require 'concurrent/collection/lock_free_stack'
|
5
|
+
require 'concurrent/configuration'
|
5
6
|
require 'concurrent/errors'
|
6
7
|
require 'concurrent/re_include'
|
7
8
|
|
@@ -313,7 +314,7 @@ module Concurrent
|
|
313
314
|
end
|
314
315
|
|
315
316
|
# @!macro promises.shortcut.on
|
316
|
-
# @return [
|
317
|
+
# @return [Event]
|
317
318
|
def any_event(*futures_and_or_events)
|
318
319
|
any_event_on default_executor, *futures_and_or_events
|
319
320
|
end
|
@@ -892,7 +893,7 @@ module Concurrent
|
|
892
893
|
private
|
893
894
|
|
894
895
|
def rejected_resolution(raise_on_reassign, state)
|
895
|
-
Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
|
+
raise Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
897
|
return false
|
897
898
|
end
|
898
899
|
|
@@ -1298,7 +1299,7 @@ module Concurrent
|
|
1298
1299
|
|
1299
1300
|
# @!macro promise.param.raise_on_reassign
|
1300
1301
|
# @param [Boolean] raise_on_reassign should method raise exception if already resolved
|
1301
|
-
# @return [self, false] false is
|
1302
|
+
# @return [self, false] false is returned when raise_on_reassign is false and the receiver
|
1302
1303
|
# is already resolved.
|
1303
1304
|
#
|
1304
1305
|
|
@@ -2074,8 +2075,8 @@ module Concurrent
|
|
2074
2075
|
|
2075
2076
|
private
|
2076
2077
|
|
2077
|
-
def resolvable?(countdown,
|
2078
|
-
|
2078
|
+
def resolvable?(countdown, event_or_future, index)
|
2079
|
+
(event_or_future.is_a?(Event) ? event_or_future.resolved? : event_or_future.fulfilled?) ||
|
2079
2080
|
# inlined super from BlockedPromise
|
2080
2081
|
countdown.zero?
|
2081
2082
|
end
|
@@ -42,16 +42,6 @@ module Concurrent
|
|
42
42
|
|
43
43
|
JRubySet
|
44
44
|
|
45
|
-
when Concurrent.on_rbx?
|
46
|
-
require 'monitor'
|
47
|
-
require 'concurrent/thread_safe/util/data_structures'
|
48
|
-
|
49
|
-
class RbxSet < ::Set
|
50
|
-
end
|
51
|
-
|
52
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxSet
|
53
|
-
RbxSet
|
54
|
-
|
55
45
|
when Concurrent.on_truffleruby?
|
56
46
|
require 'concurrent/thread_safe/util/data_structures'
|
57
47
|
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
require 'concurrent/utility/monotonic_time'
|
3
|
+
require 'concurrent/synchronization/object'
|
4
|
+
|
1
5
|
module Concurrent
|
2
6
|
module Synchronization
|
3
7
|
|
@@ -34,7 +38,7 @@ module Concurrent
|
|
34
38
|
if timeout
|
35
39
|
wait_until = Concurrent.monotonic_time + timeout
|
36
40
|
loop do
|
37
|
-
now
|
41
|
+
now = Concurrent.monotonic_time
|
38
42
|
condition_result = condition.call
|
39
43
|
return condition_result if now >= wait_until || condition_result
|
40
44
|
ns_wait wait_until - now
|
@@ -4,10 +4,8 @@ module Concurrent
|
|
4
4
|
# @!visibility private
|
5
5
|
# @!macro internal_implementation_note
|
6
6
|
class AbstractObject
|
7
|
-
|
8
|
-
# @abstract has to be implemented based on Ruby runtime
|
9
7
|
def initialize
|
10
|
-
|
8
|
+
# nothing to do
|
11
9
|
end
|
12
10
|
|
13
11
|
# @!visibility private
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
module Synchronization
|
5
|
+
case
|
6
|
+
when Concurrent.on_cruby?
|
7
|
+
def self.full_memory_barrier
|
8
|
+
# relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
|
9
|
+
# https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
|
10
|
+
end
|
11
|
+
|
12
|
+
when Concurrent.on_jruby?
|
13
|
+
require 'concurrent/utility/native_extension_loader'
|
14
|
+
def self.full_memory_barrier
|
15
|
+
JRubyAttrVolatile.full_memory_barrier
|
16
|
+
end
|
17
|
+
|
18
|
+
when Concurrent.on_truffleruby?
|
19
|
+
def self.full_memory_barrier
|
20
|
+
TruffleRuby.full_memory_barrier
|
21
|
+
end
|
22
|
+
|
23
|
+
else
|
24
|
+
warn 'Possibly unsupported Ruby implementation'
|
25
|
+
def self.full_memory_barrier
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
|
1
3
|
module Concurrent
|
2
4
|
module Synchronization
|
3
5
|
|
4
|
-
if Concurrent.on_jruby?
|
6
|
+
if Concurrent.on_jruby?
|
5
7
|
|
6
8
|
# @!visibility private
|
7
9
|
# @!macro internal_implementation_note
|
@@ -1,3 +1,8 @@
|
|
1
|
+
require 'concurrent/utility/engine'
|
2
|
+
require 'concurrent/synchronization/abstract_lockable_object'
|
3
|
+
require 'concurrent/synchronization/mutex_lockable_object'
|
4
|
+
require 'concurrent/synchronization/jruby_lockable_object'
|
5
|
+
|
1
6
|
module Concurrent
|
2
7
|
module Synchronization
|
3
8
|
|
@@ -8,8 +13,6 @@ module Concurrent
|
|
8
13
|
MutexLockableObject
|
9
14
|
when Concurrent.on_jruby?
|
10
15
|
JRubyLockableObject
|
11
|
-
when Concurrent.on_rbx?
|
12
|
-
RbxLockableObject
|
13
16
|
when Concurrent.on_truffleruby?
|
14
17
|
MutexLockableObject
|
15
18
|
else
|
@@ -1,5 +1,6 @@
|
|
1
|
+
require 'concurrent/synchronization/abstract_lockable_object'
|
2
|
+
|
1
3
|
module Concurrent
|
2
|
-
# noinspection RubyInstanceVariableNamingConvention
|
3
4
|
module Synchronization
|
4
5
|
|
5
6
|
# @!visibility private
|
@@ -26,8 +27,8 @@ module Concurrent
|
|
26
27
|
|
27
28
|
safe_initialization!
|
28
29
|
|
29
|
-
def initialize
|
30
|
-
super(
|
30
|
+
def initialize
|
31
|
+
super()
|
31
32
|
@__Lock__ = ::Mutex.new
|
32
33
|
@__Condition__ = ::ConditionVariable.new
|
33
34
|
end
|
@@ -61,8 +62,8 @@ module Concurrent
|
|
61
62
|
|
62
63
|
safe_initialization!
|
63
64
|
|
64
|
-
def initialize
|
65
|
-
super(
|
65
|
+
def initialize
|
66
|
+
super()
|
66
67
|
@__Lock__ = ::Monitor.new
|
67
68
|
@__Condition__ = @__Lock__.new_cond
|
68
69
|
end
|