concurrent-ruby 0.8.0.pre2-java → 0.9.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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -3
  3. data/README.md +111 -55
  4. data/lib/concurrent.rb +90 -14
  5. data/lib/concurrent/async.rb +143 -51
  6. data/lib/concurrent/atom.rb +131 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +34 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +27 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +234 -109
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +19 -7
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  46. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  47. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  48. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  49. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  50. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  51. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  52. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  53. data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
  54. data/lib/concurrent/executor/timer_set.rb +96 -84
  55. data/lib/concurrent/executors.rb +1 -1
  56. data/lib/concurrent/future.rb +71 -38
  57. data/lib/concurrent/immutable_struct.rb +89 -0
  58. data/lib/concurrent/ivar.rb +152 -60
  59. data/lib/concurrent/lazy_register.rb +40 -20
  60. data/lib/concurrent/maybe.rb +226 -0
  61. data/lib/concurrent/mutable_struct.rb +227 -0
  62. data/lib/concurrent/mvar.rb +44 -43
  63. data/lib/concurrent/promise.rb +229 -136
  64. data/lib/concurrent/scheduled_task.rb +341 -43
  65. data/lib/concurrent/settable_struct.rb +127 -0
  66. data/lib/concurrent/synchronization.rb +17 -0
  67. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  68. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  69. data/lib/concurrent/synchronization/condition.rb +53 -0
  70. data/lib/concurrent/synchronization/java_object.rb +34 -0
  71. data/lib/concurrent/synchronization/lock.rb +32 -0
  72. data/lib/concurrent/synchronization/monitor_object.rb +26 -0
  73. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  74. data/lib/concurrent/synchronization/object.rb +78 -0
  75. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  76. data/lib/concurrent/timer_task.rb +92 -103
  77. data/lib/concurrent/tvar.rb +42 -38
  78. data/lib/concurrent/utilities.rb +3 -1
  79. data/lib/concurrent/utility/at_exit.rb +97 -0
  80. data/lib/concurrent/utility/engine.rb +44 -0
  81. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  82. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  83. data/lib/concurrent/utility/processor_counter.rb +156 -0
  84. data/lib/concurrent/utility/timeout.rb +18 -14
  85. data/lib/concurrent/utility/timer.rb +11 -6
  86. data/lib/concurrent/version.rb +2 -1
  87. data/lib/concurrent_ruby.rb +1 -0
  88. data/lib/concurrent_ruby_ext.jar +0 -0
  89. metadata +46 -66
  90. data/lib/concurrent/actor.rb +0 -103
  91. data/lib/concurrent/actor/behaviour.rb +0 -70
  92. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  93. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  94. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  95. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  96. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  97. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  98. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  99. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  100. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  101. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  102. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  103. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  104. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  105. data/lib/concurrent/actor/context.rb +0 -154
  106. data/lib/concurrent/actor/core.rb +0 -217
  107. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  108. data/lib/concurrent/actor/envelope.rb +0 -41
  109. data/lib/concurrent/actor/errors.rb +0 -27
  110. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  111. data/lib/concurrent/actor/public_delegations.rb +0 -40
  112. data/lib/concurrent/actor/reference.rb +0 -81
  113. data/lib/concurrent/actor/root.rb +0 -37
  114. data/lib/concurrent/actor/type_check.rb +0 -48
  115. data/lib/concurrent/actor/utils.rb +0 -10
  116. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  117. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  118. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  119. data/lib/concurrent/actor/utils/pool.rb +0 -59
  120. data/lib/concurrent/actress.rb +0 -3
  121. data/lib/concurrent/agent.rb +0 -209
  122. data/lib/concurrent/atomic.rb +0 -92
  123. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  124. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  125. data/lib/concurrent/atomic/synchronization.rb +0 -51
  126. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  127. data/lib/concurrent/channel/channel.rb +0 -41
  128. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  129. data/lib/concurrent/channel/waitable_list.rb +0 -40
  130. data/lib/concurrent/channels.rb +0 -5
  131. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  132. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  133. data/lib/concurrent/collections.rb +0 -3
  134. data/lib/concurrent/dereferenceable.rb +0 -108
  135. data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
  136. data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
  137. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
  138. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
  139. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  140. data/lib/concurrent/logging.rb +0 -20
  141. data/lib/concurrent/obligation.rb +0 -171
  142. data/lib/concurrent/observable.rb +0 -73
  143. data/lib/concurrent/options_parser.rb +0 -48
  144. data/lib/concurrent/utility/processor_count.rb +0 -152
  145. data/lib/extension_helper.rb +0 -37
@@ -0,0 +1,236 @@
1
+ # Copyright (c) 2013 Brian Durand
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Concurrent
23
+
24
+ # @!visibility private
25
+ class AbstractThreadLocalVar
26
+
27
+ begin
28
+ require 'weakref'
29
+
30
+ # @!visibility private
31
+ class WeakReference
32
+
33
+ # The object id of the object being referenced.
34
+ attr_reader :referenced_object_id
35
+
36
+ # This implementation of a weak reference simply wraps the standard WeakRef implementation
37
+ # that comes with the Ruby standard library.
38
+ def initialize(obj)
39
+ @referenced_object_id = obj.__id__
40
+ @ref = ::WeakRef.new(obj)
41
+ end
42
+
43
+ def object
44
+ @ref.__getobj__
45
+ rescue => e
46
+ # Jruby implementation uses RefError while MRI uses WeakRef::RefError
47
+ if (defined?(RefError) && e.is_a?(RefError)) || (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError))
48
+ nil
49
+ else
50
+ raise e
51
+ end
52
+ end
53
+ end
54
+
55
+ rescue LoadError
56
+
57
+ require 'monitor'
58
+
59
+ # This is a pure ruby implementation of a weak reference. It is much more
60
+ # efficient than the WeakRef implementation bundled in MRI 1.8 and 1.9
61
+ # subclass Delegator which is very heavy to instantiate and utilizes a
62
+ # because it does not fair amount of memory under Ruby 1.8.
63
+ #
64
+ # @!visibility private
65
+ class WeakReference
66
+
67
+ # The object id of the object being referenced.
68
+ attr_reader :referenced_object_id
69
+
70
+ # @!visibility private
71
+ class ReferencePointer
72
+ def initialize(object)
73
+ @referenced_object_id = object.__id__
74
+ add_backreference(object)
75
+ end
76
+
77
+ def cleanup
78
+ obj = ObjectSpace._id2ref(@referenced_object_id) rescue nil
79
+ remove_backreference(obj) if obj
80
+ end
81
+
82
+ def object
83
+ obj = ObjectSpace._id2ref(@referenced_object_id)
84
+ obj if verify_backreferences(obj)
85
+ rescue RangeError
86
+ nil
87
+ end
88
+
89
+ private
90
+
91
+ # Verify that the object is the same one originally set for the weak reference.
92
+ def verify_backreferences(obj)
93
+ return nil unless supports_backreference?(obj)
94
+ backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
95
+ backreferences && backreferences.include?(object_id)
96
+ end
97
+
98
+ # Add a backreference to the object.
99
+ def add_backreference(obj)
100
+ return unless supports_backreference?(obj)
101
+ backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
102
+ unless backreferences
103
+ backreferences = []
104
+ obj.instance_variable_set(:@__weak_backreferences__, backreferences)
105
+ end
106
+ backreferences << object_id
107
+ end
108
+
109
+ # Remove backreferences from the object.
110
+ def remove_backreference(obj)
111
+ return unless supports_backreference?(obj)
112
+ backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
113
+ if backreferences
114
+ backreferences.dup.delete(object_id)
115
+ obj.send(:remove_instance_variable, :@__weak_backreferences__) if backreferences.empty?
116
+ end
117
+ end
118
+
119
+ def supports_backreference?(obj)
120
+ obj.respond_to?(:instance_variable_get) && obj.respond_to?(:instance_variable_defined?)
121
+ rescue NoMethodError
122
+ false
123
+ end
124
+ end
125
+
126
+ private_constant :ReferencePointer
127
+
128
+ @@weak_references = {}
129
+ @@lock = Monitor.new
130
+
131
+ # Finalizer that cleans up weak references when references are destroyed.
132
+ @@reference_finalizer = lambda do |object_id|
133
+ @@lock.synchronize do
134
+ reference_pointer = @@weak_references.delete(object_id)
135
+ reference_pointer.cleanup if reference_pointer
136
+ end
137
+ end
138
+
139
+ # Create a new weak reference to an object. The existence of the weak reference
140
+ # will not prevent the garbage collector from reclaiming the referenced object.
141
+ def initialize(obj)
142
+ @referenced_object_id = obj.__id__
143
+ @@lock.synchronize do
144
+ @reference_pointer = ReferencePointer.new(obj)
145
+ @@weak_references[self.object_id] = @reference_pointer
146
+ end
147
+ ObjectSpace.define_finalizer(self, @@reference_finalizer)
148
+ end
149
+
150
+ # Get the reference object. If the object has already been garbage collected,
151
+ # then this method will return nil.
152
+ def object
153
+ if @reference_pointer
154
+ obj = @reference_pointer.object
155
+ unless obj
156
+ @@lock.synchronize do
157
+ @@weak_references.delete(object_id)
158
+ @reference_pointer.cleanup
159
+ @reference_pointer = nil
160
+ end
161
+ end
162
+ obj
163
+ end
164
+ end
165
+ end
166
+
167
+ private_constant :WeakReference
168
+ end
169
+
170
+ # The classes behave similar to Hashes, but the keys in the map are not strong references
171
+ # and can be reclaimed by the garbage collector at any time. When a key is reclaimed, the
172
+ # map entry will be removed.
173
+ #
174
+ # @!visibility private
175
+ class WeakKeyMap
176
+
177
+ # Create a new map. Values added to the hash will be cleaned up by the garbage
178
+ # collector if there are no other reference except in the map.
179
+ def initialize
180
+ @values = {}
181
+ @references_to_keys_map = {}
182
+ @lock = Monitor.new
183
+ @reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
184
+ end
185
+
186
+ # Get a value from the map by key. If the value has been reclaimed by the garbage
187
+ # collector, this will return nil.
188
+ def [](key)
189
+ @lock.synchronize do
190
+ rkey = ref_key(key)
191
+ @values[rkey] if rkey
192
+ end
193
+ end
194
+
195
+ # Add a key/value to the map.
196
+ def []=(key, value)
197
+ ObjectSpace.define_finalizer(key, @reference_cleanup)
198
+ @lock.synchronize do
199
+ @references_to_keys_map[key.__id__] = WeakReference.new(key)
200
+ @values[key.__id__] = value
201
+ end
202
+ end
203
+
204
+ # Remove the value associated with the key from the map.
205
+ def delete(key)
206
+ @lock.synchronize do
207
+ rkey = ref_key(key)
208
+ if rkey
209
+ @references_to_keys_map.delete(rkey)
210
+ @values.delete(rkey)
211
+ else
212
+ nil
213
+ end
214
+ end
215
+ end
216
+
217
+ # Get an array of keys that have not yet been garbage collected.
218
+ def keys
219
+ @values.keys.collect{|rkey| @references_to_keys_map[rkey].object}.compact
220
+ end
221
+
222
+ private
223
+
224
+ def ref_key (key)
225
+ ref = @references_to_keys_map[key.__id__]
226
+ if ref && ref.object
227
+ ref.referenced_object_id
228
+ else
229
+ nil
230
+ end
231
+ end
232
+ end
233
+
234
+ private_constant :WeakKeyMap
235
+ end
236
+ end
@@ -3,6 +3,9 @@ require 'concurrent/atomic_reference/concurrent_update_error'
3
3
  module Concurrent
4
4
 
5
5
  # Define update methods that use direct paths
6
+ #
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
6
9
  module AtomicDirectUpdate
7
10
 
8
11
  # @!macro [attach] atomic_reference_method_update
@@ -10,7 +13,7 @@ module Concurrent
10
13
  # Pass the current value to the given block, replacing it
11
14
  # with the block's result. May retry if the value changes
12
15
  # during the block's execution.
13
- #
16
+ #
14
17
  # @yield [Object] Calculate a new value for the atomic reference using
15
18
  # given (old) value
16
19
  # @yieldparam [Object] old_value the starting value of the atomic reference
@@ -24,17 +27,45 @@ module Concurrent
24
27
  # @!macro [attach] atomic_reference_method_try_update
25
28
  #
26
29
  # Pass the current value to the given block, replacing it
30
+ # with the block's result. Return nil if the update fails.
31
+ #
32
+ # @yield [Object] Calculate a new value for the atomic reference using
33
+ # given (old) value
34
+ # @yieldparam [Object] old_value the starting value of the atomic reference
35
+ #
36
+ # @note This method was altered to avoid raising an exception by default.
37
+ # Instead, this method now returns `nil` in case of failure. For more info,
38
+ # please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
39
+ #
40
+ # @return [Object] the new value, or nil if update failed
41
+ def try_update
42
+ old_value = get
43
+ new_value = yield old_value
44
+
45
+ return unless compare_and_set old_value, new_value
46
+
47
+ new_value
48
+ end
49
+
50
+ # @!macro [attach] atomic_reference_method_try_update!
51
+ #
52
+ # Pass the current value to the given block, replacing it
27
53
  # with the block's result. Raise an exception if the update
28
54
  # fails.
29
- #
55
+ #
30
56
  # @yield [Object] Calculate a new value for the atomic reference using
31
57
  # given (old) value
32
58
  # @yieldparam [Object] old_value the starting value of the atomic reference
33
59
  #
60
+ # @note This behavior mimics the behavior of the original
61
+ # `AtomicReference#try_update` API. The reason this was changed was to
62
+ # avoid raising exceptions (which are inherently slow) by default. For more
63
+ # info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
64
+ #
34
65
  # @return [Object] the new value
35
66
  #
36
67
  # @raise [Concurrent::ConcurrentUpdateError] if the update fails
37
- def try_update
68
+ def try_update!
38
69
  old_value = get
39
70
  new_value = yield old_value
40
71
  unless compare_and_set(old_value, new_value)
@@ -1,12 +1,15 @@
1
- require_relative '../../extension_helper'
1
+ require 'concurrent/utility/native_extension_loader'
2
2
 
3
- if defined?(Concurrent::JavaAtomic)
3
+ if defined?(Concurrent::JavaAtomicReference)
4
4
  require 'concurrent/atomic_reference/direct_update'
5
5
 
6
6
  module Concurrent
7
7
 
8
8
  # @!macro atomic_reference
9
- class JavaAtomic
9
+ #
10
+ # @!visibility private
11
+ # @!macro internal_implementation_note
12
+ class JavaAtomicReference
10
13
  include Concurrent::AtomicDirectUpdate
11
14
  end
12
15
  end
@@ -5,45 +5,32 @@ require 'concurrent/atomic_reference/numeric_cas_wrapper'
5
5
  module Concurrent
6
6
 
7
7
  # @!macro atomic_reference
8
- class MutexAtomic
8
+ #
9
+ # @!visibility private
10
+ # @!macro internal_implementation_note
11
+ class MutexAtomicReference
9
12
  include Concurrent::AtomicDirectUpdate
10
13
  include Concurrent::AtomicNumericCompareAndSetWrapper
11
14
 
12
- # @!macro [attach] atomic_reference_method_initialize
15
+ # @!macro atomic_reference_method_initialize
13
16
  def initialize(value = nil)
14
17
  @mutex = Mutex.new
15
18
  @value = value
16
19
  end
17
20
 
18
- # @!macro [attach] atomic_reference_method_get
19
- #
20
- # Gets the current value.
21
- #
22
- # @return [Object] the current value
21
+ # @!macro atomic_reference_method_get
23
22
  def get
24
23
  @mutex.synchronize { @value }
25
24
  end
26
25
  alias_method :value, :get
27
26
 
28
- # @!macro [attach] atomic_reference_method_set
29
- #
30
- # Sets to the given value.
31
- #
32
- # @param [Object] new_value the new value
33
- #
34
- # @return [Object] the new value
27
+ # @!macro atomic_reference_method_set
35
28
  def set(new_value)
36
29
  @mutex.synchronize { @value = new_value }
37
30
  end
38
31
  alias_method :value=, :set
39
32
 
40
- # @!macro [attach] atomic_reference_method_get_and_set
41
- #
42
- # Atomically sets to the given value and returns the old value.
43
- #
44
- # @param [Object] new_value the new value
45
- #
46
- # @return [Object] the old value
33
+ # @!macro atomic_reference_method_get_and_set
47
34
  def get_and_set(new_value)
48
35
  @mutex.synchronize do
49
36
  old_value = @value
@@ -53,25 +40,16 @@ module Concurrent
53
40
  end
54
41
  alias_method :swap, :get_and_set
55
42
 
56
- # @!macro [attach] atomic_reference_method_compare_and_set
57
- #
58
- # Atomically sets the value to the given updated value if
59
- # the current value == the expected value.
60
- #
61
- # @param [Object] old_value the expected value
62
- # @param [Object] new_value the new value
63
- #
64
- # @return [Boolean] `true` if successful. A `false` return indicates
65
- # that the actual value was not equal to the expected value.
66
- def _compare_and_set(old_value, new_value) #:nodoc:
67
- return false unless @mutex.try_lock
68
- begin
69
- return false unless @value.equal? old_value
70
- @value = new_value
71
- ensure
72
- @mutex.unlock
43
+ # @!macro atomic_reference_method_compare_and_set
44
+ def _compare_and_set(old_value, new_value)
45
+ @mutex.synchronize do
46
+ if @value.equal? old_value
47
+ @value = new_value
48
+ true
49
+ else
50
+ false
51
+ end
73
52
  end
74
- true
75
53
  end
76
54
  end
77
55
  end
@@ -1,6 +1,9 @@
1
1
  module Concurrent
2
2
 
3
3
  # Special "compare and set" handling of numeric values.
4
+ #
5
+ # @!visibility private
6
+ # @!macro internal_implementation_note
4
7
  module AtomicNumericCompareAndSetWrapper
5
8
 
6
9
  # @!macro atomic_reference_method_compare_and_set
@@ -7,7 +7,10 @@ module Concurrent
7
7
  #
8
8
  # @note Extends `Rubinius::AtomicReference` version adding aliases
9
9
  # and numeric logic.
10
- class RbxAtomic < Rubinius::AtomicReference
10
+ #
11
+ # @!visibility private
12
+ # @!macro internal_implementation_note
13
+ class RbxAtomicReference < Rubinius::AtomicReference
11
14
  alias _compare_and_set compare_and_set
12
15
  include Concurrent::AtomicDirectUpdate
13
16
  include Concurrent::AtomicNumericCompareAndSetWrapper
@@ -1,12 +1,15 @@
1
- if defined? Concurrent::CAtomic
2
- require_relative '../../extension_helper'
1
+ if defined? Concurrent::CAtomicReference
2
+ require 'concurrent/utility/native_extension_loader'
3
3
  require 'concurrent/atomic_reference/direct_update'
4
4
  require 'concurrent/atomic_reference/numeric_cas_wrapper'
5
5
 
6
6
  module Concurrent
7
7
 
8
8
  # @!macro atomic_reference
9
- class CAtomic
9
+ #
10
+ # @!visibility private
11
+ # @!macro internal_implementation_note
12
+ class CAtomicReference
10
13
  include Concurrent::AtomicDirectUpdate
11
14
  include Concurrent::AtomicNumericCompareAndSetWrapper
12
15