concurrent-ruby 0.9.2-java → 1.0.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/README.md +86 -120
  4. data/lib/concurrent.rb +14 -5
  5. data/lib/concurrent/agent.rb +587 -0
  6. data/lib/concurrent/array.rb +39 -0
  7. data/lib/concurrent/async.rb +296 -149
  8. data/lib/concurrent/atom.rb +135 -45
  9. data/lib/concurrent/atomic/abstract_thread_local_var.rb +38 -0
  10. data/lib/concurrent/atomic/atomic_boolean.rb +83 -118
  11. data/lib/concurrent/atomic/atomic_fixnum.rb +101 -163
  12. data/lib/concurrent/atomic/atomic_reference.rb +1 -8
  13. data/lib/concurrent/atomic/count_down_latch.rb +62 -103
  14. data/lib/concurrent/atomic/cyclic_barrier.rb +3 -1
  15. data/lib/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent/atomic/java_count_down_latch.rb +39 -0
  17. data/lib/concurrent/atomic/java_thread_local_var.rb +50 -0
  18. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +60 -0
  19. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +91 -0
  20. data/lib/concurrent/atomic/mutex_count_down_latch.rb +43 -0
  21. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  22. data/lib/concurrent/atomic/read_write_lock.rb +5 -4
  23. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  24. data/lib/concurrent/atomic/ruby_thread_local_var.rb +172 -0
  25. data/lib/concurrent/atomic/semaphore.rb +84 -178
  26. data/lib/concurrent/atomic/thread_local_var.rb +65 -294
  27. data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
  28. data/lib/concurrent/atomic_reference/jruby.rb +1 -1
  29. data/lib/concurrent/atomic_reference/mutex_atomic.rb +14 -8
  30. data/lib/concurrent/atomic_reference/ruby.rb +1 -1
  31. data/lib/concurrent/atomics.rb +7 -37
  32. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
  33. data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
  34. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  35. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  36. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  37. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +144 -0
  38. data/lib/concurrent/collection/map/synchronized_map_backend.rb +86 -0
  39. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  40. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  41. data/lib/concurrent/concern/dereferenceable.rb +9 -24
  42. data/lib/concurrent/concern/logging.rb +1 -1
  43. data/lib/concurrent/concern/obligation.rb +11 -20
  44. data/lib/concurrent/concern/observable.rb +38 -13
  45. data/lib/concurrent/configuration.rb +23 -152
  46. data/lib/concurrent/constants.rb +8 -0
  47. data/lib/concurrent/delay.rb +14 -12
  48. data/lib/concurrent/exchanger.rb +339 -41
  49. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  50. data/lib/concurrent/executor/executor_service.rb +23 -359
  51. data/lib/concurrent/executor/immediate_executor.rb +3 -2
  52. data/lib/concurrent/executor/java_executor_service.rb +100 -0
  53. data/lib/concurrent/executor/java_single_thread_executor.rb +3 -3
  54. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -4
  55. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  56. data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -66
  57. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +25 -22
  58. data/lib/concurrent/executor/safe_task_executor.rb +6 -7
  59. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  60. data/lib/concurrent/executor/serialized_execution.rb +10 -33
  61. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  62. data/lib/concurrent/executor/simple_executor_service.rb +1 -10
  63. data/lib/concurrent/executor/single_thread_executor.rb +20 -10
  64. data/lib/concurrent/executor/timer_set.rb +8 -10
  65. data/lib/concurrent/executors.rb +12 -2
  66. data/lib/concurrent/future.rb +6 -4
  67. data/lib/concurrent/hash.rb +35 -0
  68. data/lib/concurrent/immutable_struct.rb +5 -1
  69. data/lib/concurrent/ivar.rb +12 -16
  70. data/lib/concurrent/lazy_register.rb +11 -8
  71. data/lib/concurrent/map.rb +180 -0
  72. data/lib/concurrent/maybe.rb +6 -3
  73. data/lib/concurrent/mutable_struct.rb +7 -6
  74. data/lib/concurrent/mvar.rb +26 -2
  75. data/lib/concurrent/{executor/executor.rb → options.rb} +5 -29
  76. data/lib/concurrent/promise.rb +7 -5
  77. data/lib/concurrent/scheduled_task.rb +13 -71
  78. data/lib/concurrent/settable_struct.rb +5 -4
  79. data/lib/concurrent/synchronization.rb +15 -3
  80. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  81. data/lib/concurrent/synchronization/abstract_object.rb +7 -146
  82. data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
  83. data/lib/concurrent/synchronization/condition.rb +6 -4
  84. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  85. data/lib/concurrent/synchronization/jruby_object.rb +44 -0
  86. data/lib/concurrent/synchronization/lock.rb +3 -2
  87. data/lib/concurrent/synchronization/lockable_object.rb +72 -0
  88. data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
  89. data/lib/concurrent/synchronization/mri_object.rb +43 -0
  90. data/lib/concurrent/synchronization/object.rb +140 -73
  91. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  92. data/lib/concurrent/synchronization/rbx_object.rb +30 -73
  93. data/lib/concurrent/synchronization/volatile.rb +34 -0
  94. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  95. data/lib/concurrent/thread_safe/util.rb +14 -0
  96. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  97. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +30 -0
  98. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  99. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  100. data/lib/concurrent/thread_safe/util/striped64.rb +241 -0
  101. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  102. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  103. data/lib/concurrent/timer_task.rb +3 -4
  104. data/lib/concurrent/tuple.rb +86 -0
  105. data/lib/concurrent/tvar.rb +5 -1
  106. data/lib/concurrent/utility/at_exit.rb +1 -1
  107. data/lib/concurrent/utility/engine.rb +4 -0
  108. data/lib/concurrent/utility/monotonic_time.rb +3 -4
  109. data/lib/concurrent/utility/native_extension_loader.rb +50 -30
  110. data/lib/concurrent/version.rb +2 -2
  111. data/lib/concurrent_ruby_ext.jar +0 -0
  112. metadata +47 -12
  113. data/lib/concurrent/atomic/condition.rb +0 -78
  114. data/lib/concurrent/collection/priority_queue.rb +0 -360
  115. data/lib/concurrent/synchronization/java_object.rb +0 -34
  116. data/lib/concurrent/synchronization/monitor_object.rb +0 -27
  117. data/lib/concurrent/synchronization/mutex_object.rb +0 -43
  118. data/lib/concurrent/utilities.rb +0 -5
  119. data/lib/concurrent/utility/timeout.rb +0 -39
  120. data/lib/concurrent/utility/timer.rb +0 -26
  121. data/lib/concurrent_ruby.rb +0 -2
@@ -1,12 +1,13 @@
1
+ require 'concurrent/constants'
1
2
  require 'concurrent/errors'
3
+ require 'concurrent/configuration'
2
4
  require 'concurrent/ivar'
3
5
  require 'concurrent/collection/copy_on_notify_observer_set'
4
- require 'concurrent/executor/executor'
5
6
  require 'concurrent/utility/monotonic_time'
6
- require 'concurrent/concern/deprecation'
7
7
 
8
8
  module Concurrent
9
- include Concern::Deprecation
9
+
10
+ autoload :Options, 'concurrent/options'
10
11
 
11
12
  # `ScheduledTask` is a close relative of `Concurrent::Future` but with one
12
13
  # important difference: A `Future` is set to execute as soon as possible
@@ -161,24 +162,20 @@ module Concurrent
161
162
  #
162
163
  # @raise [ArgumentError] When no block is given
163
164
  # @raise [ArgumentError] When given a time that is in the past
164
- #
165
- # @!macro [attach] deprecated_scheduling_by_clock_time
166
- #
167
- # @note Scheduling is now based on a monotonic clock. This makes the timer much
168
- # more accurate, but only when scheduling based on a delay interval.
169
- # Scheduling a task based on a clock time is deprecated. It will still work
170
- # but will not be supported in the 1.0 release.
171
165
  def initialize(delay, opts = {}, &task)
172
166
  raise ArgumentError.new('no block given') unless block_given?
173
- super(IVar::NO_VALUE, opts, &nil)
167
+ raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0
168
+
169
+ super(NULL, opts, &nil)
170
+
174
171
  synchronize do
175
- @delay = calculate_delay!(delay) # may raise exception
176
172
  ns_set_state(:unscheduled)
177
173
  @parent = opts.fetch(:timer_set, Concurrent.global_timer_set)
178
174
  @args = get_arguments_from(opts)
175
+ @delay = delay.to_f
179
176
  @task = task
180
177
  @time = nil
181
- @executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
178
+ @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
182
179
  self.observers = Collection::CopyOnNotifyObserverSet.new
183
180
  end
184
181
  end
@@ -190,16 +187,6 @@ module Concurrent
190
187
  synchronize { @delay }
191
188
  end
192
189
 
193
- # The `delay` value given at instanciation.
194
- #
195
- # @return [Float] the initial delay.
196
- #
197
- # @deprecated use {#initial_delay} instead
198
- def delay
199
- deprecated_method 'delay', 'initial_delay'
200
- initial_delay
201
- end
202
-
203
190
  # The monotonic time at which the the task is scheduled to be executed.
204
191
  #
205
192
  # @return [Float] the schedule time or nil if `unscheduled`
@@ -228,16 +215,6 @@ module Concurrent
228
215
  synchronize { ns_check_state?(:processing) }
229
216
  end
230
217
 
231
- # In the task execution in progress?
232
- #
233
- # @return [Boolean] true if the task is in the given state else false
234
- #
235
- # @deprecated Use {#processing?} instead.
236
- def in_progress?
237
- deprecated_method 'in_progress?', 'processing?'
238
- processing?
239
- end
240
-
241
218
  # Cancel this task and prevent it from executing. A task can only be
242
219
  # cancelled if it is pending or unscheduled.
243
220
  #
@@ -253,17 +230,6 @@ module Concurrent
253
230
  end
254
231
  end
255
232
 
256
- # Cancel this task and prevent it from executing. A task can only be
257
- # cancelled if it is `:pending` or `:unscheduled`.
258
- #
259
- # @return [Boolean] true if successfully cancelled else false
260
- #
261
- # @deprecated Use {#cancel} instead.
262
- def stop
263
- deprecated_method 'stop', 'cancel'
264
- cancel
265
- end
266
-
267
233
  # Reschedule the task using the original delay and the current time.
268
234
  # A task can only be reset while it is `:pending`.
269
235
  #
@@ -281,7 +247,9 @@ module Concurrent
281
247
  #
282
248
  # @raise [ArgumentError] When given a time that is in the past
283
249
  def reschedule(delay)
284
- synchronize{ ns_reschedule(calculate_delay!(delay)) }
250
+ delay = delay.to_f
251
+ raise ArgumentError.new('seconds must be greater than zero') if delay < 0.0
252
+ synchronize{ ns_reschedule(delay) }
285
253
  end
286
254
 
287
255
  # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending`
@@ -306,8 +274,6 @@ module Concurrent
306
274
  # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state
307
275
  #
308
276
  # @raise [ArgumentError] if no block is given
309
- #
310
- # @!macro deprecated_scheduling_by_clock_time
311
277
  def self.execute(delay, opts = {}, &task)
312
278
  new(delay, opts, &task).execute
313
279
  end
@@ -348,29 +314,5 @@ module Concurrent
348
314
  return false unless ns_check_state?(:pending)
349
315
  @parent.send(:remove_task, self) && ns_schedule(delay)
350
316
  end
351
-
352
- # Calculate the actual delay in seconds based on the given delay.
353
- #
354
- # @param [Float] delay the number of seconds to wait for before executing the task
355
- #
356
- # @return [Float] the number of seconds to delay
357
- #
358
- # @raise [ArgumentError] if the intended execution time is not in the future
359
- # @raise [ArgumentError] if no block is given
360
- #
361
- # @!macro deprecated_scheduling_by_clock_time
362
- #
363
- # @!visibility private
364
- def calculate_delay!(delay)
365
- if delay.is_a?(Time)
366
- deprecated 'Use an interval not a clock time; schedule is now based on a monotonic clock'
367
- now = Time.now
368
- raise ArgumentError.new('schedule time must be in the future') if delay <= now
369
- delay.to_f - now.to_f
370
- else
371
- raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0
372
- delay.to_f
373
- end
374
- end
375
317
  end
376
318
  end
@@ -74,8 +74,9 @@ module Concurrent
74
74
  # @raise [Concurrent::ImmutabilityError] if the given member has already been set
75
75
  def []=(member, value)
76
76
  if member.is_a? Integer
77
- if member >= @values.length
78
- raise IndexError.new("offset #{member} too large for struct(size:#{@values.length})")
77
+ length = synchronize { @values.length }
78
+ if member >= length
79
+ raise IndexError.new("offset #{member} too large for struct(size:#{length})")
79
80
  end
80
81
  synchronize do
81
82
  unless @values[member].nil?
@@ -101,10 +102,10 @@ module Concurrent
101
102
  FACTORY.define_struct(clazz_name, args, &block)
102
103
  end
103
104
 
104
- FACTORY = Class.new(Synchronization::Object) do
105
+ FACTORY = Class.new(Synchronization::LockableObject) do
105
106
  def define_struct(name, members, &block)
106
107
  synchronize do
107
- clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::Object, name, members, &block)
108
+ clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block)
108
109
  members.each_with_index do |member, index|
109
110
  clazz.send(:define_method, member) do
110
111
  synchronize { @values[index] }
@@ -1,16 +1,28 @@
1
1
  require 'concurrent/utility/engine'
2
+
2
3
  require 'concurrent/synchronization/abstract_object'
3
- require 'concurrent/synchronization/java_object'
4
- require 'concurrent/synchronization/mutex_object'
5
- require 'concurrent/synchronization/monitor_object'
4
+ require 'concurrent/utility/native_extension_loader' # load native parts first
5
+ Concurrent.load_native_extensions
6
+
7
+ require 'concurrent/synchronization/mri_object'
8
+ require 'concurrent/synchronization/jruby_object'
6
9
  require 'concurrent/synchronization/rbx_object'
7
10
  require 'concurrent/synchronization/object'
11
+ require 'concurrent/synchronization/volatile'
12
+
13
+ require 'concurrent/synchronization/abstract_lockable_object'
14
+ require 'concurrent/synchronization/mri_lockable_object'
15
+ require 'concurrent/synchronization/jruby_lockable_object'
16
+ require 'concurrent/synchronization/rbx_lockable_object'
17
+
18
+ require 'concurrent/synchronization/lockable_object'
8
19
 
9
20
  require 'concurrent/synchronization/condition'
10
21
  require 'concurrent/synchronization/lock'
11
22
 
12
23
  module Concurrent
13
24
  # {include:file:doc/synchronization.md}
25
+ # {include:file:doc/synchronization-notes.md}
14
26
  module Synchronization
15
27
  end
16
28
  end
@@ -0,0 +1,98 @@
1
+ module Concurrent
2
+ module Synchronization
3
+
4
+ # @!visibility private
5
+ class AbstractLockableObject < Object
6
+
7
+ protected
8
+
9
+ # @!macro [attach] synchronization_object_method_synchronize
10
+ #
11
+ # @yield runs the block synchronized against this object,
12
+ # equivalent of java's `synchronize(this) {}`
13
+ # @note can by made public in descendants if required by `public :synchronize`
14
+ def synchronize
15
+ raise NotImplementedError
16
+ end
17
+
18
+ # @!macro [attach] synchronization_object_method_ns_wait_until
19
+ #
20
+ # Wait until condition is met or timeout passes,
21
+ # protects against spurious wake-ups.
22
+ # @param [Numeric, nil] timeout in seconds, `nil` means no timeout
23
+ # @yield condition to be met
24
+ # @yieldreturn [true, false]
25
+ # @return [true, false] if condition met
26
+ # @note only to be used inside synchronized block
27
+ # @note to provide direct access to this method in a descendant add method
28
+ # ```
29
+ # def wait_until(timeout = nil, &condition)
30
+ # synchronize { ns_wait_until(timeout, &condition) }
31
+ # end
32
+ # ```
33
+ def ns_wait_until(timeout = nil, &condition)
34
+ if timeout
35
+ wait_until = Concurrent.monotonic_time + timeout
36
+ loop do
37
+ now = Concurrent.monotonic_time
38
+ condition_result = condition.call
39
+ return condition_result if now >= wait_until || condition_result
40
+ ns_wait wait_until - now
41
+ end
42
+ else
43
+ ns_wait timeout until condition.call
44
+ true
45
+ end
46
+ end
47
+
48
+ # @!macro [attach] synchronization_object_method_ns_wait
49
+ #
50
+ # Wait until another thread calls #signal or #broadcast,
51
+ # spurious wake-ups can happen.
52
+ #
53
+ # @param [Numeric, nil] timeout in seconds, `nil` means no timeout
54
+ # @return [self]
55
+ # @note only to be used inside synchronized block
56
+ # @note to provide direct access to this method in a descendant add method
57
+ # ```
58
+ # def wait(timeout = nil)
59
+ # synchronize { ns_wait(timeout) }
60
+ # end
61
+ # ```
62
+ def ns_wait(timeout = nil)
63
+ raise NotImplementedError
64
+ end
65
+
66
+ # @!macro [attach] synchronization_object_method_ns_signal
67
+ #
68
+ # Signal one waiting thread.
69
+ # @return [self]
70
+ # @note only to be used inside synchronized block
71
+ # @note to provide direct access to this method in a descendant add method
72
+ # ```
73
+ # def signal
74
+ # synchronize { ns_signal }
75
+ # end
76
+ # ```
77
+ def ns_signal
78
+ raise NotImplementedError
79
+ end
80
+
81
+ # @!macro [attach] synchronization_object_method_ns_broadcast
82
+ #
83
+ # Broadcast to all waiting threads.
84
+ # @return [self]
85
+ # @note only to be used inside synchronized block
86
+ # @note to provide direct access to this method in a descendant add method
87
+ # ```
88
+ # def broadcast
89
+ # synchronize { ns_broadcast }
90
+ # end
91
+ # ```
92
+ def ns_broadcast
93
+ raise NotImplementedError
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -1,162 +1,23 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
- # @!macro synchronization_object
5
4
  # @!visibility private
5
+ # @!macro internal_implementation_note
6
6
  class AbstractObject
7
7
 
8
- # @!macro [attach] synchronization_object_method_initialize
9
- #
10
- # @abstract for helper ivar initialization if needed,
11
- # otherwise it can be left empty. It has to call ns_initialize.
12
- def initialize(*args, &block)
8
+ # @abstract has to be implemented based on Ruby runtime
9
+ def initialize
13
10
  raise NotImplementedError
14
11
  end
15
12
 
16
- protected
17
-
18
- # @!macro [attach] synchronization_object_method_synchronize
19
- #
20
- # @yield runs the block synchronized against this object,
21
- # equivalent of java's `synchronize(this) {}`
22
- # @note can by made public in descendants if required by `public :synchronize`
23
- def synchronize
24
- raise NotImplementedError
25
- end
26
-
27
- # @!macro [attach] synchronization_object_method_ns_initialize
28
- #
29
- # initialization of the object called inside synchronize block
30
- # @note has to be called manually when required in children of this class
31
- # @example
32
- # class Child < Concurrent::Synchornization::Object
33
- # def initialize(*args, &block)
34
- # super(&nil)
35
- # synchronize { ns_initialize(*args, &block) }
36
- # end
37
- #
38
- # def ns_initialize(*args, &block)
39
- # @args = args
40
- # end
41
- # end
42
- def ns_initialize(*args, &block)
43
- end
44
-
45
- # @!macro [attach] synchronization_object_method_ns_wait_until
46
- #
47
- # Wait until condition is met or timeout passes,
48
- # protects against spurious wake-ups.
49
- # @param [Numeric, nil] timeout in seconds, `nil` means no timeout
50
- # @yield condition to be met
51
- # @yieldreturn [true, false]
52
- # @return [true, false] if condition met
53
- # @note only to be used inside synchronized block
54
- # @note to provide direct access to this method in a descendant add method
55
- # ```
56
- # def wait_until(timeout = nil, &condition)
57
- # synchronize { ns_wait_until(timeout, &condition) }
58
- # end
59
- # ```
60
- def ns_wait_until(timeout = nil, &condition)
61
- if timeout
62
- wait_until = Concurrent.monotonic_time + timeout
63
- loop do
64
- now = Concurrent.monotonic_time
65
- condition_result = condition.call
66
- # 0.001 correction to avoid error when `wait_until - now` is smaller than 0.0005 and rounded to 0
67
- # when passed to java #wait(long timeout)
68
- return condition_result if (now + 0.001) >= wait_until || condition_result
69
- ns_wait wait_until - now
70
- end
71
- else
72
- ns_wait timeout until condition.call
73
- true
74
- end
75
- end
76
-
77
- # @!macro [attach] synchronization_object_method_ns_wait
78
- #
79
- # Wait until another thread calls #signal or #broadcast,
80
- # spurious wake-ups can happen.
81
- #
82
- # @param [Numeric, nil] timeout in seconds, `nil` means no timeout
83
- # @return [self]
84
- # @note only to be used inside synchronized block
85
- # @note to provide direct access to this method in a descendant add method
86
- # ```
87
- # def wait(timeout = nil)
88
- # synchronize { ns_wait(timeout) }
89
- # end
90
- # ```
91
- def ns_wait(timeout = nil)
13
+ # @!visibility private
14
+ # @abstract
15
+ def full_memory_barrier
92
16
  raise NotImplementedError
93
17
  end
94
18
 
95
- # @!macro [attach] synchronization_object_method_ns_signal
96
- #
97
- # Signal one waiting thread.
98
- # @return [self]
99
- # @note only to be used inside synchronized block
100
- # @note to provide direct access to this method in a descendant add method
101
- # ```
102
- # def signal
103
- # synchronize { ns_signal }
104
- # end
105
- # ```
106
- def ns_signal
107
- raise NotImplementedError
108
- end
109
-
110
- # @!macro [attach] synchronization_object_method_ns_broadcast
111
- #
112
- # Broadcast to all waiting threads.
113
- # @return [self]
114
- # @note only to be used inside synchronized block
115
- # @note to provide direct access to this method in a descendant add method
116
- # ```
117
- # def broadcast
118
- # synchronize { ns_broadcast }
119
- # end
120
- # ```
121
- def ns_broadcast
122
- raise NotImplementedError
123
- end
124
-
125
- # @!macro [attach] synchronization_object_method_ensure_ivar_visibility
126
- #
127
- # Allows to construct immutable objects where all fields are visible after initialization, not requiring
128
- # further synchronization on access.
129
- # @example
130
- # class AClass
131
- # attr_reader :val
132
- # def initialize(val)
133
- # @val = val # final value, after assignment it's not changed (just convention, not enforced)
134
- # ensure_ivar_visibility!
135
- # # now it can be shared as Java's final field
136
- # end
137
- # end
138
- def ensure_ivar_visibility!
139
- raise NotImplementedError
140
- end
141
-
142
- # @!macro [attach] synchronization_object_method_self_attr_volatile
143
- #
144
- # creates methods for reading and writing to a instance variable with volatile (Java semantic) instance variable
145
- # return [Array<Symbol>] names of defined method names
146
19
  def self.attr_volatile(*names)
147
- names.each do |name|
148
- ivar = :"@volatile_#{name}"
149
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
150
- def #{name}
151
- #{ivar}
152
- end
153
-
154
- def #{name}=(value)
155
- #{ivar} = value
156
- end
157
- RUBY
158
- end
159
- names.map { |n| [n, :"#{n}="] }.flatten
20
+ raise NotImplementedError
160
21
  end
161
22
  end
162
23
  end