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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -1
  3. data/Gemfile +1 -2
  4. data/README.md +23 -20
  5. data/Rakefile +75 -65
  6. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  7. data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
  8. data/lib/concurrent-ruby/concurrent/array.rb +3 -13
  9. data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
  10. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
  11. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
  12. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
  13. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +81 -151
  14. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
  15. data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
  18. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
  19. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
  20. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
  21. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
  22. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
  23. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
  24. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
  25. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +5 -3
  26. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
  27. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
  28. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  29. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
  30. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
  31. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
  32. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
  33. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +2 -2
  34. data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +16 -8
  35. data/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb +23 -20
  36. data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
  37. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  38. data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
  39. data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
  40. data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
  41. data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
  42. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
  43. data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +4 -0
  44. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +6 -9
  45. data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +5 -0
  46. data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +7 -0
  47. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
  48. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
  50. data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +6 -2
  51. data/lib/concurrent-ruby/concurrent/hash.rb +5 -12
  52. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
  53. data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
  54. data/lib/concurrent-ruby/concurrent/map.rb +43 -39
  55. data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
  56. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
  57. data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
  58. data/lib/concurrent-ruby/concurrent/promise.rb +1 -1
  59. data/lib/concurrent-ruby/concurrent/promises.rb +40 -29
  60. data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
  61. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +1 -1
  62. data/lib/concurrent-ruby/concurrent/set.rb +0 -10
  63. data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
  64. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
  65. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
  66. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
  67. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  68. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
  69. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
  70. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
  71. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
  72. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
  73. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  74. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
  75. data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
  76. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
  77. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
  78. data/lib/concurrent-ruby/concurrent/timer_task.rb +59 -9
  79. data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
  80. data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
  81. data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
  82. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
  83. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
  84. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
  85. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +118 -58
  86. data/lib/concurrent-ruby/concurrent/version.rb +1 -1
  87. metadata +13 -17
  88. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  89. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
  90. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
  91. data/lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb +0 -927
  92. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
  93. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
  94. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
  95. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
  96. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
  97. 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