concurrent-ruby 1.0.5 → 1.1.6
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 +5 -5
- data/CHANGELOG.md +115 -0
- data/Gemfile +42 -0
- data/{LICENSE.txt → LICENSE.md} +2 -0
- data/README.md +242 -105
- data/Rakefile +332 -0
- data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
- data/lib/concurrent-ruby/concurrent-ruby.rb +1 -0
- data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
- data/lib/concurrent-ruby/concurrent/array.rb +66 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
- data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
- data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
- data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
- data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
- data/lib/concurrent-ruby/concurrent/map.rb +337 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
- data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
- data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
- data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
- data/lib/concurrent-ruby/concurrent/set.rb +66 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
- data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- metadata +146 -131
- data/lib/concurrent/array.rb +0 -39
- data/lib/concurrent/atomic/atomic_reference.rb +0 -51
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
- data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
- data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
- data/lib/concurrent/atomic_reference/jruby.rb +0 -16
- data/lib/concurrent/atomic_reference/rbx.rb +0 -22
- data/lib/concurrent/atomic_reference/ruby.rb +0 -32
- data/lib/concurrent/atomics.rb +0 -53
- data/lib/concurrent/edge.rb +0 -26
- data/lib/concurrent/hash.rb +0 -36
- data/lib/concurrent/lazy_register.rb +0 -81
- data/lib/concurrent/map.rb +0 -240
- data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
- data/lib/concurrent/synchronization/truffle_object.rb +0 -31
- data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
- data/lib/concurrent/utility/at_exit.rb +0 -97
- data/lib/concurrent/utility/native_extension_loader.rb +0 -73
- data/lib/concurrent/version.rb +0 -4
@@ -0,0 +1,58 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
# Methods form module A included to a module B, which is already included into class C,
|
4
|
+
# will not be visible in the C class. If this module is extended to B then A's methods
|
5
|
+
# are correctly made visible to C.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# module A
|
9
|
+
# def a
|
10
|
+
# :a
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# module B1
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class C1
|
18
|
+
# include B1
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# module B2
|
22
|
+
# extend Concurrent::ReInclude
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# class C2
|
26
|
+
# include B2
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# B1.send :include, A
|
30
|
+
# B2.send :include, A
|
31
|
+
#
|
32
|
+
# C1.new.respond_to? :a # => false
|
33
|
+
# C2.new.respond_to? :a # => true
|
34
|
+
module ReInclude
|
35
|
+
# @!visibility private
|
36
|
+
def included(base)
|
37
|
+
(@re_include_to_bases ||= []) << [:include, base]
|
38
|
+
super(base)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @!visibility private
|
42
|
+
def extended(base)
|
43
|
+
(@re_include_to_bases ||= []) << [:extend, base]
|
44
|
+
super(base)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @!visibility private
|
48
|
+
def include(*modules)
|
49
|
+
result = super(*modules)
|
50
|
+
modules.reverse.each do |module_being_included|
|
51
|
+
(@re_include_to_bases ||= []).each do |method, mod|
|
52
|
+
mod.send method, module_being_included
|
53
|
+
end
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
File without changes
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'concurrent/utility/engine'
|
2
|
+
require 'concurrent/thread_safe/util'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
|
7
|
+
# @!macro concurrent_set
|
8
|
+
#
|
9
|
+
# A thread-safe subclass of Set. This version locks against the object
|
10
|
+
# itself for every method call, ensuring only one thread can be reading
|
11
|
+
# or writing at a time. This includes iteration methods like `#each`.
|
12
|
+
#
|
13
|
+
# @note `a += b` is **not** a **thread-safe** operation on
|
14
|
+
# `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set`
|
15
|
+
# which is union of `a` and `b`, then it writes the union to `a`.
|
16
|
+
# The read and write are independent operations they do not form a single atomic
|
17
|
+
# operation therefore when two `+=` operations are executed concurrently updates
|
18
|
+
# may be lost. Use `#merge` instead.
|
19
|
+
#
|
20
|
+
# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set`
|
21
|
+
|
22
|
+
|
23
|
+
# @!macro internal_implementation_note
|
24
|
+
SetImplementation = case
|
25
|
+
when Concurrent.on_cruby?
|
26
|
+
# Because MRI never runs code in parallel, the existing
|
27
|
+
# non-thread-safe structures should usually work fine.
|
28
|
+
::Set
|
29
|
+
|
30
|
+
when Concurrent.on_jruby?
|
31
|
+
require 'jruby/synchronized'
|
32
|
+
|
33
|
+
class JRubySet < ::Set
|
34
|
+
include JRuby::Synchronized
|
35
|
+
end
|
36
|
+
JRubySet
|
37
|
+
|
38
|
+
when Concurrent.on_rbx?
|
39
|
+
require 'monitor'
|
40
|
+
require 'concurrent/thread_safe/util/data_structures'
|
41
|
+
|
42
|
+
class RbxSet < ::Set
|
43
|
+
end
|
44
|
+
ThreadSafe::Util.make_synchronized_on_rbx Concurrent::RbxSet
|
45
|
+
RbxSet
|
46
|
+
|
47
|
+
when Concurrent.on_truffleruby?
|
48
|
+
require 'concurrent/thread_safe/util/data_structures'
|
49
|
+
|
50
|
+
class TruffleRubySet < ::Set
|
51
|
+
end
|
52
|
+
|
53
|
+
ThreadSafe::Util.make_synchronized_on_truffleruby Concurrent::TruffleRubySet
|
54
|
+
TruffleRubySet
|
55
|
+
|
56
|
+
else
|
57
|
+
warn 'Possibly unsupported Ruby implementation'
|
58
|
+
::Set
|
59
|
+
end
|
60
|
+
private_constant :SetImplementation
|
61
|
+
|
62
|
+
# @!macro concurrent_set
|
63
|
+
class Set < SetImplementation
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -91,6 +91,16 @@ module Concurrent
|
|
91
91
|
raise NameError.new("no member '#{member}' in struct")
|
92
92
|
end
|
93
93
|
|
94
|
+
private
|
95
|
+
|
96
|
+
# @!visibility private
|
97
|
+
def initialize_copy(original)
|
98
|
+
synchronize do
|
99
|
+
super(original)
|
100
|
+
ns_initialize_copy
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
94
104
|
# @!macro struct_new
|
95
105
|
def self.new(*args, &block)
|
96
106
|
clazz_name = nil
|
@@ -107,6 +117,7 @@ module Concurrent
|
|
107
117
|
synchronize do
|
108
118
|
clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block)
|
109
119
|
members.each_with_index do |member, index|
|
120
|
+
clazz.send :remove_method, member if clazz.instance_methods.include? member
|
110
121
|
clazz.send(:define_method, member) do
|
111
122
|
synchronize { @values[index] }
|
112
123
|
end
|
@@ -7,15 +7,14 @@ Concurrent.load_native_extensions
|
|
7
7
|
require 'concurrent/synchronization/mri_object'
|
8
8
|
require 'concurrent/synchronization/jruby_object'
|
9
9
|
require 'concurrent/synchronization/rbx_object'
|
10
|
-
require 'concurrent/synchronization/
|
10
|
+
require 'concurrent/synchronization/truffleruby_object'
|
11
11
|
require 'concurrent/synchronization/object'
|
12
12
|
require 'concurrent/synchronization/volatile'
|
13
13
|
|
14
14
|
require 'concurrent/synchronization/abstract_lockable_object'
|
15
|
-
require 'concurrent/synchronization/
|
15
|
+
require 'concurrent/synchronization/mutex_lockable_object'
|
16
16
|
require 'concurrent/synchronization/jruby_lockable_object'
|
17
17
|
require 'concurrent/synchronization/rbx_lockable_object'
|
18
|
-
require 'concurrent/synchronization/truffle_lockable_object'
|
19
18
|
|
20
19
|
require 'concurrent/synchronization/lockable_object'
|
21
20
|
|
@@ -23,8 +22,8 @@ require 'concurrent/synchronization/condition'
|
|
23
22
|
require 'concurrent/synchronization/lock'
|
24
23
|
|
25
24
|
module Concurrent
|
26
|
-
# {include:file:
|
27
|
-
# {include:file:
|
25
|
+
# {include:file:docs-source/synchronization.md}
|
26
|
+
# {include:file:docs-source/synchronization-notes.md}
|
28
27
|
module Synchronization
|
29
28
|
end
|
30
29
|
end
|
data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb
RENAMED
@@ -6,7 +6,7 @@ module Concurrent
|
|
6
6
|
|
7
7
|
protected
|
8
8
|
|
9
|
-
# @!macro
|
9
|
+
# @!macro synchronization_object_method_synchronize
|
10
10
|
#
|
11
11
|
# @yield runs the block synchronized against this object,
|
12
12
|
# equivalent of java's `synchronize(this) {}`
|
@@ -15,7 +15,7 @@ module Concurrent
|
|
15
15
|
raise NotImplementedError
|
16
16
|
end
|
17
17
|
|
18
|
-
# @!macro
|
18
|
+
# @!macro synchronization_object_method_ns_wait_until
|
19
19
|
#
|
20
20
|
# Wait until condition is met or timeout passes,
|
21
21
|
# protects against spurious wake-ups.
|
@@ -45,7 +45,7 @@ module Concurrent
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
# @!macro
|
48
|
+
# @!macro synchronization_object_method_ns_wait
|
49
49
|
#
|
50
50
|
# Wait until another thread calls #signal or #broadcast,
|
51
51
|
# spurious wake-ups can happen.
|
@@ -63,7 +63,7 @@ module Concurrent
|
|
63
63
|
raise NotImplementedError
|
64
64
|
end
|
65
65
|
|
66
|
-
# @!macro
|
66
|
+
# @!macro synchronization_object_method_ns_signal
|
67
67
|
#
|
68
68
|
# Signal one waiting thread.
|
69
69
|
# @return [self]
|
@@ -78,7 +78,7 @@ module Concurrent
|
|
78
78
|
raise NotImplementedError
|
79
79
|
end
|
80
80
|
|
81
|
-
# @!macro
|
81
|
+
# @!macro synchronization_object_method_ns_broadcast
|
82
82
|
#
|
83
83
|
# Broadcast to all waiting threads.
|
84
84
|
# @return [self]
|
File without changes
|
@@ -11,7 +11,7 @@ module Concurrent
|
|
11
11
|
ns_initialize(*values)
|
12
12
|
end
|
13
13
|
|
14
|
-
# @!macro
|
14
|
+
# @!macro struct_length
|
15
15
|
#
|
16
16
|
# Returns the number of struct members.
|
17
17
|
#
|
@@ -21,7 +21,7 @@ module Concurrent
|
|
21
21
|
end
|
22
22
|
alias_method :size, :length
|
23
23
|
|
24
|
-
# @!macro
|
24
|
+
# @!macro struct_members
|
25
25
|
#
|
26
26
|
# Returns the struct members as an array of symbols.
|
27
27
|
#
|
@@ -115,9 +115,20 @@ module Concurrent
|
|
115
115
|
self.class.new(*self.to_h.merge(other, &block).values)
|
116
116
|
end
|
117
117
|
|
118
|
+
# @!visibility private
|
119
|
+
def ns_initialize_copy
|
120
|
+
@values = @values.map do |val|
|
121
|
+
begin
|
122
|
+
val.clone
|
123
|
+
rescue TypeError
|
124
|
+
val
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
118
129
|
# @!visibility private
|
119
130
|
def pr_underscore(clazz)
|
120
|
-
word = clazz.to_s
|
131
|
+
word = clazz.to_s.dup # dup string to workaround JRuby 9.2.0.0 bug https://github.com/jruby/jruby/issues/5229
|
121
132
|
word.gsub!(/::/, '/')
|
122
133
|
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
123
134
|
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
@@ -138,18 +149,21 @@ module Concurrent
|
|
138
149
|
end
|
139
150
|
unless name.nil?
|
140
151
|
begin
|
152
|
+
parent.send :remove_const, name if parent.const_defined?(name, false)
|
141
153
|
parent.const_set(name, clazz)
|
142
|
-
|
154
|
+
clazz
|
143
155
|
rescue NameError
|
144
156
|
raise NameError.new("identifier #{name} needs to be constant")
|
145
157
|
end
|
146
158
|
end
|
147
159
|
members.each_with_index do |member, index|
|
160
|
+
clazz.send :remove_method, member if clazz.instance_methods.include? member
|
148
161
|
clazz.send(:define_method, member) do
|
149
162
|
@values[index]
|
150
163
|
end
|
151
164
|
end
|
152
165
|
clazz.class_exec(&block) unless block.nil?
|
166
|
+
clazz.singleton_class.send :alias_method, :[], :new
|
153
167
|
clazz
|
154
168
|
end
|
155
169
|
end
|
File without changes
|
@@ -5,18 +5,18 @@ module Concurrent
|
|
5
5
|
# @!macro internal_implementation_note
|
6
6
|
LockableObjectImplementation = case
|
7
7
|
when Concurrent.on_cruby? && Concurrent.ruby_version(:<=, 1, 9, 3)
|
8
|
-
|
8
|
+
MonitorLockableObject
|
9
9
|
when Concurrent.on_cruby? && Concurrent.ruby_version(:>, 1, 9, 3)
|
10
|
-
|
10
|
+
MutexLockableObject
|
11
11
|
when Concurrent.on_jruby?
|
12
12
|
JRubyLockableObject
|
13
13
|
when Concurrent.on_rbx?
|
14
14
|
RbxLockableObject
|
15
|
-
when Concurrent.
|
16
|
-
|
15
|
+
when Concurrent.on_truffleruby?
|
16
|
+
MutexLockableObject
|
17
17
|
else
|
18
18
|
warn 'Possibly unsupported Ruby implementation'
|
19
|
-
|
19
|
+
MonitorLockableObject
|
20
20
|
end
|
21
21
|
private_constant :LockableObjectImplementation
|
22
22
|
|
@@ -31,7 +31,7 @@ module Concurrent
|
|
31
31
|
# `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and
|
32
32
|
# `Thread#wakeup` will not work on all platforms.
|
33
33
|
#
|
34
|
-
# @see
|
34
|
+
# @see Event implementation as an example of this class use
|
35
35
|
#
|
36
36
|
# @example simple
|
37
37
|
# class AnClass < Synchronization::Object
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module Concurrent
|
2
|
+
# noinspection RubyInstanceVariableNamingConvention
|
2
3
|
module Synchronization
|
3
4
|
|
4
5
|
# @!visibility private
|
5
6
|
# @!macro internal_implementation_note
|
6
|
-
|
7
|
+
module ConditionSignalling
|
7
8
|
protected
|
8
9
|
|
9
10
|
def ns_signal
|
10
|
-
@
|
11
|
+
@__Condition__.signal
|
11
12
|
self
|
12
13
|
end
|
13
14
|
|
14
15
|
def ns_broadcast
|
15
|
-
@
|
16
|
+
@__Condition__.broadcast
|
16
17
|
self
|
17
18
|
end
|
18
19
|
end
|
@@ -20,50 +21,54 @@ module Concurrent
|
|
20
21
|
|
21
22
|
# @!visibility private
|
22
23
|
# @!macro internal_implementation_note
|
23
|
-
class
|
24
|
+
class MutexLockableObject < AbstractLockableObject
|
25
|
+
include ConditionSignalling
|
26
|
+
|
24
27
|
safe_initialization!
|
25
28
|
|
26
29
|
def initialize(*defaults)
|
27
30
|
super(*defaults)
|
28
|
-
@
|
29
|
-
@
|
31
|
+
@__Lock__ = ::Mutex.new
|
32
|
+
@__Condition__ = ::ConditionVariable.new
|
30
33
|
end
|
31
34
|
|
32
35
|
protected
|
33
36
|
|
34
37
|
def synchronize
|
35
|
-
if @
|
38
|
+
if @__Lock__.owned?
|
36
39
|
yield
|
37
40
|
else
|
38
|
-
@
|
41
|
+
@__Lock__.synchronize { yield }
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
45
|
def ns_wait(timeout = nil)
|
43
|
-
@
|
46
|
+
@__Condition__.wait @__Lock__, timeout
|
44
47
|
self
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
# @!visibility private
|
49
52
|
# @!macro internal_implementation_note
|
50
|
-
class
|
53
|
+
class MonitorLockableObject < AbstractLockableObject
|
54
|
+
include ConditionSignalling
|
55
|
+
|
51
56
|
safe_initialization!
|
52
57
|
|
53
58
|
def initialize(*defaults)
|
54
59
|
super(*defaults)
|
55
|
-
@
|
56
|
-
@
|
60
|
+
@__Lock__ = ::Monitor.new
|
61
|
+
@__Condition__ = @__Lock__.new_cond
|
57
62
|
end
|
58
63
|
|
59
64
|
protected
|
60
65
|
|
61
66
|
def synchronize # TODO may be a problem with lock.synchronize { lock.wait }
|
62
|
-
@
|
67
|
+
@__Lock__.synchronize { yield }
|
63
68
|
end
|
64
69
|
|
65
70
|
def ns_wait(timeout = nil)
|
66
|
-
@
|
71
|
+
@__Condition__.wait timeout
|
67
72
|
self
|
68
73
|
end
|
69
74
|
end
|