concurrent-ruby 1.1.10 → 1.3.3
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 +47 -1
- data/Gemfile +1 -2
- data/README.md +23 -20
- data/Rakefile +75 -65
- 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 +3 -13
- 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/collection/map/synchronized_map_backend.rb +23 -20
- 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/fixed_thread_pool.rb +4 -0
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +6 -9
- data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +5 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +7 -0
- 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/executor/timer_set.rb +6 -2
- data/lib/concurrent-ruby/concurrent/hash.rb +5 -12
- 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 +40 -29
- 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/data_structures.rb +1 -37
- data/lib/concurrent-ruby/concurrent/timer_task.rb +59 -9
- 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 +118 -58
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- metadata +13 -17
- 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/collection/map/atomic_reference_map_backend.rb +0 -927
- 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
- data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +0 -118
@@ -1,45 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Synchronization
|
3
|
-
|
4
|
-
if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
|
5
|
-
|
6
|
-
# @!visibility private
|
7
|
-
module JRubyAttrVolatile
|
8
|
-
def self.included(base)
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def attr_volatile(*names)
|
14
|
-
names.each do |name|
|
15
|
-
|
16
|
-
ivar = :"@volatile_#{name}"
|
17
|
-
|
18
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
19
|
-
def #{name}
|
20
|
-
instance_variable_get_volatile(:#{ivar})
|
21
|
-
end
|
22
|
-
|
23
|
-
def #{name}=(value)
|
24
|
-
instance_variable_set_volatile(:#{ivar}, value)
|
25
|
-
end
|
26
|
-
RUBY
|
27
|
-
|
28
|
-
end
|
29
|
-
names.map { |n| [n, :"#{n}="] }.flatten
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# @!visibility private
|
35
|
-
# @!macro internal_implementation_note
|
36
|
-
class JRubyObject < AbstractObject
|
37
|
-
include JRubyAttrVolatile
|
38
|
-
|
39
|
-
def initialize
|
40
|
-
# nothing to do
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Synchronization
|
3
|
-
|
4
|
-
# @!visibility private
|
5
|
-
module MriAttrVolatile
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
def attr_volatile(*names)
|
12
|
-
names.each do |name|
|
13
|
-
ivar = :"@volatile_#{name}"
|
14
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
15
|
-
def #{name}
|
16
|
-
#{ivar}
|
17
|
-
end
|
18
|
-
|
19
|
-
def #{name}=(value)
|
20
|
-
#{ivar} = value
|
21
|
-
end
|
22
|
-
RUBY
|
23
|
-
end
|
24
|
-
names.map { |n| [n, :"#{n}="] }.flatten
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def full_memory_barrier
|
29
|
-
# relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
|
30
|
-
# https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# @!visibility private
|
35
|
-
# @!macro internal_implementation_note
|
36
|
-
class MriObject < AbstractObject
|
37
|
-
include MriAttrVolatile
|
38
|
-
|
39
|
-
def initialize
|
40
|
-
# nothing to do
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Synchronization
|
3
|
-
|
4
|
-
# @!visibility private
|
5
|
-
# @!macro internal_implementation_note
|
6
|
-
class RbxLockableObject < AbstractLockableObject
|
7
|
-
safe_initialization!
|
8
|
-
|
9
|
-
def initialize(*defaults)
|
10
|
-
super(*defaults)
|
11
|
-
@__Waiters__ = []
|
12
|
-
@__owner__ = nil
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize_copy(other)
|
16
|
-
super
|
17
|
-
@__Waiters__ = []
|
18
|
-
@__owner__ = nil
|
19
|
-
end
|
20
|
-
|
21
|
-
protected
|
22
|
-
|
23
|
-
def synchronize(&block)
|
24
|
-
if @__owner__ == Thread.current
|
25
|
-
yield
|
26
|
-
else
|
27
|
-
result = nil
|
28
|
-
Rubinius.synchronize(self) do
|
29
|
-
begin
|
30
|
-
@__owner__ = Thread.current
|
31
|
-
result = yield
|
32
|
-
ensure
|
33
|
-
@__owner__ = nil
|
34
|
-
end
|
35
|
-
end
|
36
|
-
result
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def ns_wait(timeout = nil)
|
41
|
-
wchan = Rubinius::Channel.new
|
42
|
-
|
43
|
-
begin
|
44
|
-
@__Waiters__.push wchan
|
45
|
-
Rubinius.unlock(self)
|
46
|
-
signaled = wchan.receive_timeout timeout
|
47
|
-
ensure
|
48
|
-
Rubinius.lock(self)
|
49
|
-
|
50
|
-
if !signaled && !@__Waiters__.delete(wchan)
|
51
|
-
# we timed out, but got signaled afterwards,
|
52
|
-
# so pass that signal on to the next waiter
|
53
|
-
@__Waiters__.shift << true unless @__Waiters__.empty?
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
self
|
58
|
-
end
|
59
|
-
|
60
|
-
def ns_signal
|
61
|
-
@__Waiters__.shift << true unless @__Waiters__.empty?
|
62
|
-
self
|
63
|
-
end
|
64
|
-
|
65
|
-
def ns_broadcast
|
66
|
-
@__Waiters__.shift << true until @__Waiters__.empty?
|
67
|
-
self
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Synchronization
|
3
|
-
|
4
|
-
# @!visibility private
|
5
|
-
module RbxAttrVolatile
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
def attr_volatile(*names)
|
13
|
-
names.each do |name|
|
14
|
-
ivar = :"@volatile_#{name}"
|
15
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
16
|
-
def #{name}
|
17
|
-
Rubinius.memory_barrier
|
18
|
-
#{ivar}
|
19
|
-
end
|
20
|
-
|
21
|
-
def #{name}=(value)
|
22
|
-
#{ivar} = value
|
23
|
-
Rubinius.memory_barrier
|
24
|
-
end
|
25
|
-
RUBY
|
26
|
-
end
|
27
|
-
names.map { |n| [n, :"#{n}="] }.flatten
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def full_memory_barrier
|
33
|
-
# Rubinius instance variables are not volatile so we need to insert barrier
|
34
|
-
# TODO (pitr 26-Nov-2015): check comments like ^
|
35
|
-
Rubinius.memory_barrier
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# @!visibility private
|
40
|
-
# @!macro internal_implementation_note
|
41
|
-
class RbxObject < AbstractObject
|
42
|
-
include RbxAttrVolatile
|
43
|
-
|
44
|
-
def initialize
|
45
|
-
# nothing to do
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Synchronization
|
3
|
-
|
4
|
-
# @!visibility private
|
5
|
-
module TruffleRubyAttrVolatile
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
def attr_volatile(*names)
|
12
|
-
names.each do |name|
|
13
|
-
ivar = :"@volatile_#{name}"
|
14
|
-
|
15
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
16
|
-
def #{name}
|
17
|
-
full_memory_barrier
|
18
|
-
#{ivar}
|
19
|
-
end
|
20
|
-
|
21
|
-
def #{name}=(value)
|
22
|
-
#{ivar} = value
|
23
|
-
full_memory_barrier
|
24
|
-
end
|
25
|
-
RUBY
|
26
|
-
end
|
27
|
-
|
28
|
-
names.map { |n| [n, :"#{n}="] }.flatten
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def full_memory_barrier
|
33
|
-
TruffleRuby.full_memory_barrier
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# @!visibility private
|
38
|
-
# @!macro internal_implementation_note
|
39
|
-
class TruffleRubyObject < AbstractObject
|
40
|
-
include TruffleRubyAttrVolatile
|
41
|
-
|
42
|
-
def initialize
|
43
|
-
# nothing to do
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,118 +0,0 @@
|
|
1
|
-
require 'concurrent/thread_safe/util'
|
2
|
-
require 'concurrent/thread_safe/util/volatile'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
# @!visibility private
|
7
|
-
module ThreadSafe
|
8
|
-
|
9
|
-
# @!visibility private
|
10
|
-
module Util
|
11
|
-
|
12
|
-
# Provides a cheapest possible (mainly in terms of memory usage) +Mutex+
|
13
|
-
# with the +ConditionVariable+ bundled in.
|
14
|
-
#
|
15
|
-
# Usage:
|
16
|
-
# class A
|
17
|
-
# include CheapLockable
|
18
|
-
#
|
19
|
-
# def do_exlusively
|
20
|
-
# cheap_synchronize { yield }
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# def wait_for_something
|
24
|
-
# cheap_synchronize do
|
25
|
-
# cheap_wait until resource_available?
|
26
|
-
# do_something
|
27
|
-
# cheap_broadcast # wake up others
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# @!visibility private
|
33
|
-
module CheapLockable
|
34
|
-
private
|
35
|
-
engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
36
|
-
if engine == 'rbx'
|
37
|
-
# Making use of the Rubinius' ability to lock via object headers to avoid the overhead of the extra Mutex objects.
|
38
|
-
def cheap_synchronize
|
39
|
-
Rubinius.lock(self)
|
40
|
-
begin
|
41
|
-
yield
|
42
|
-
ensure
|
43
|
-
Rubinius.unlock(self)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def cheap_wait
|
48
|
-
wchan = Rubinius::Channel.new
|
49
|
-
|
50
|
-
begin
|
51
|
-
waiters = @waiters ||= []
|
52
|
-
waiters.push wchan
|
53
|
-
Rubinius.unlock(self)
|
54
|
-
signaled = wchan.receive_timeout nil
|
55
|
-
ensure
|
56
|
-
Rubinius.lock(self)
|
57
|
-
|
58
|
-
unless signaled or waiters.delete(wchan)
|
59
|
-
# we timed out, but got signaled afterwards (e.g. while waiting to
|
60
|
-
# acquire @lock), so pass that signal on to the next waiter
|
61
|
-
waiters.shift << true unless waiters.empty?
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
def cheap_broadcast
|
69
|
-
waiters = @waiters ||= []
|
70
|
-
waiters.shift << true until waiters.empty?
|
71
|
-
self
|
72
|
-
end
|
73
|
-
elsif engine == 'jruby'
|
74
|
-
# Use Java's native synchronized (this) { wait(); notifyAll(); } to avoid the overhead of the extra Mutex objects
|
75
|
-
require 'jruby'
|
76
|
-
|
77
|
-
def cheap_synchronize
|
78
|
-
JRuby.reference0(self).synchronized { yield }
|
79
|
-
end
|
80
|
-
|
81
|
-
def cheap_wait
|
82
|
-
JRuby.reference0(self).wait
|
83
|
-
end
|
84
|
-
|
85
|
-
def cheap_broadcast
|
86
|
-
JRuby.reference0(self).notify_all
|
87
|
-
end
|
88
|
-
else
|
89
|
-
require 'thread'
|
90
|
-
|
91
|
-
extend Volatile
|
92
|
-
attr_volatile :mutex
|
93
|
-
|
94
|
-
# Non-reentrant Mutex#syncrhonize
|
95
|
-
def cheap_synchronize
|
96
|
-
true until (my_mutex = mutex) || cas_mutex(nil, my_mutex = Mutex.new)
|
97
|
-
my_mutex.synchronize { yield }
|
98
|
-
end
|
99
|
-
|
100
|
-
# Releases this object's +cheap_synchronize+ lock and goes to sleep waiting for other threads to +cheap_broadcast+, reacquires the lock on wakeup.
|
101
|
-
# Must only be called in +cheap_broadcast+'s block.
|
102
|
-
def cheap_wait
|
103
|
-
conditional_variable = @conditional_variable ||= ConditionVariable.new
|
104
|
-
conditional_variable.wait(mutex)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Wakes up all threads waiting for this object's +cheap_synchronize+ lock.
|
108
|
-
# Must only be called in +cheap_broadcast+'s block.
|
109
|
-
def cheap_broadcast
|
110
|
-
if conditional_variable = @conditional_variable
|
111
|
-
conditional_variable.broadcast
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|