concurrent-ruby 1.1.5 → 1.1.10
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 +65 -1
- data/Gemfile +6 -10
- data/{LICENSE.md → LICENSE.txt} +18 -20
- data/README.md +46 -23
- data/Rakefile +46 -44
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
- data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +10 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_reference.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +0 -0
- 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 +0 -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 +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +18 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +4 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +60 -40
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +26 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -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 → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
- data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +13 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +33 -36
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +29 -15
- 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 -7
- 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 +19 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
- 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 +46 -42
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +5 -5
- 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 +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +14 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +12 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +29 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +19 -11
- data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +11 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +3 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +12 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +6 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/truffleruby_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.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 → concurrent-ruby/concurrent}/thread_safe/util/data_structures.rb +26 -1
- 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 +1 -1
- 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}/thread_safe/util.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +11 -34
- data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +19 -56
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +0 -0
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -33
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
- data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
- metadata +132 -132
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/utility/at_exit.rb +0 -97
- data/lib/concurrent/utility/monotonic_time.rb +0 -58
- data/lib/concurrent/version.rb +0 -3
- data/lib/concurrent-ruby.rb +0 -1
@@ -32,6 +32,12 @@ module Concurrent
|
|
32
32
|
@__Condition__ = ::ConditionVariable.new
|
33
33
|
end
|
34
34
|
|
35
|
+
def initialize_copy(other)
|
36
|
+
super
|
37
|
+
@__Lock__ = ::Mutex.new
|
38
|
+
@__Condition__ = ::ConditionVariable.new
|
39
|
+
end
|
40
|
+
|
35
41
|
protected
|
36
42
|
|
37
43
|
def synchronize
|
@@ -61,6 +67,12 @@ module Concurrent
|
|
61
67
|
@__Condition__ = @__Lock__.new_cond
|
62
68
|
end
|
63
69
|
|
70
|
+
def initialize_copy(other)
|
71
|
+
super
|
72
|
+
@__Lock__ = ::Monitor.new
|
73
|
+
@__Condition__ = @__Lock__.new_cond
|
74
|
+
end
|
75
|
+
|
64
76
|
protected
|
65
77
|
|
66
78
|
def synchronize # TODO may be a problem with lock.synchronize { lock.wait }
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -12,12 +12,37 @@ end
|
|
12
12
|
module Concurrent
|
13
13
|
module ThreadSafe
|
14
14
|
module Util
|
15
|
+
def self.make_synchronized_on_cruby(klass)
|
16
|
+
klass.class_eval do
|
17
|
+
def initialize(*args, &block)
|
18
|
+
@_monitor = Monitor.new
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize_copy(other)
|
23
|
+
# make sure a copy is not sharing a monitor with the original object!
|
24
|
+
@_monitor = Monitor.new
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
klass.superclass.instance_methods(false).each do |method|
|
30
|
+
klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
31
|
+
def #{method}(*args)
|
32
|
+
monitor = @_monitor
|
33
|
+
monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.")
|
34
|
+
monitor.synchronize { super }
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
15
40
|
def self.make_synchronized_on_rbx(klass)
|
16
41
|
klass.class_eval do
|
17
42
|
private
|
18
43
|
|
19
44
|
def _mon_initialize
|
20
|
-
@_monitor
|
45
|
+
@_monitor ||= Monitor.new # avoid double initialisation
|
21
46
|
end
|
22
47
|
|
23
48
|
def self.new(*args)
|
File without changes
|
@@ -97,7 +97,7 @@ module Concurrent
|
|
97
97
|
# TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
|
98
98
|
# TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created
|
99
99
|
# hide from yardoc in a method
|
100
|
-
attr_reader
|
100
|
+
attr_reader :padding_0, :padding_1, :padding_2, :padding_3, :padding_4, :padding_5, :padding_6, :padding_7, :padding_8, :padding_9, :padding_10, :padding_11
|
101
101
|
end
|
102
102
|
padding
|
103
103
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -25,9 +25,7 @@ module Concurrent
|
|
25
25
|
# Should the task experience an unrecoverable crash only the task thread will
|
26
26
|
# crash. This makes the `TimerTask` very fault tolerant. Additionally, the
|
27
27
|
# `TimerTask` thread can respond to the success or failure of the task,
|
28
|
-
# performing logging or ancillary operations.
|
29
|
-
# configured with a timeout value allowing it to kill a task that runs too
|
30
|
-
# long.
|
28
|
+
# performing logging or ancillary operations.
|
31
29
|
#
|
32
30
|
# One other advantage of `TimerTask` is that it forces the business logic to
|
33
31
|
# be completely decoupled from the concurrency logic. The business logic can
|
@@ -48,9 +46,7 @@ module Concurrent
|
|
48
46
|
# {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
|
49
47
|
# Observable} module. On execution the `TimerTask` will notify the observers
|
50
48
|
# with three arguments: time of execution, the result of the block (or nil on
|
51
|
-
# failure), and any raised exceptions (or nil on success).
|
52
|
-
# interval is exceeded the observer will receive a `Concurrent::TimeoutError`
|
53
|
-
# object as the third argument.
|
49
|
+
# failure), and any raised exceptions (or nil on success).
|
54
50
|
#
|
55
51
|
# @!macro copy_options
|
56
52
|
#
|
@@ -59,20 +55,18 @@ module Concurrent
|
|
59
55
|
# task.execute
|
60
56
|
#
|
61
57
|
# task.execution_interval #=> 60 (default)
|
62
|
-
# task.timeout_interval #=> 30 (default)
|
63
58
|
#
|
64
59
|
# # wait 60 seconds...
|
65
60
|
# #=> 'Boom!'
|
66
61
|
#
|
67
62
|
# task.shutdown #=> true
|
68
63
|
#
|
69
|
-
# @example Configuring `:execution_interval`
|
70
|
-
# task = Concurrent::TimerTask.new(execution_interval: 5
|
64
|
+
# @example Configuring `:execution_interval`
|
65
|
+
# task = Concurrent::TimerTask.new(execution_interval: 5) do
|
71
66
|
# puts 'Boom!'
|
72
67
|
# end
|
73
68
|
#
|
74
69
|
# task.execution_interval #=> 5
|
75
|
-
# task.timeout_interval #=> 5
|
76
70
|
#
|
77
71
|
# @example Immediate execution with `:run_now`
|
78
72
|
# task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' }
|
@@ -115,15 +109,13 @@ module Concurrent
|
|
115
109
|
# def update(time, result, ex)
|
116
110
|
# if result
|
117
111
|
# print "(#{time}) Execution successfully returned #{result}\n"
|
118
|
-
# elsif ex.is_a?(Concurrent::TimeoutError)
|
119
|
-
# print "(#{time}) Execution timed out\n"
|
120
112
|
# else
|
121
113
|
# print "(#{time}) Execution failed with error #{ex}\n"
|
122
114
|
# end
|
123
115
|
# end
|
124
116
|
# end
|
125
117
|
#
|
126
|
-
# task = Concurrent::TimerTask.new(execution_interval: 1
|
118
|
+
# task = Concurrent::TimerTask.new(execution_interval: 1){ 42 }
|
127
119
|
# task.add_observer(TaskObserver.new)
|
128
120
|
# task.execute
|
129
121
|
# sleep 4
|
@@ -133,7 +125,7 @@ module Concurrent
|
|
133
125
|
# #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42
|
134
126
|
# task.shutdown
|
135
127
|
#
|
136
|
-
# task = Concurrent::TimerTask.new(execution_interval: 1
|
128
|
+
# task = Concurrent::TimerTask.new(execution_interval: 1){ sleep }
|
137
129
|
# task.add_observer(TaskObserver.new)
|
138
130
|
# task.execute
|
139
131
|
#
|
@@ -169,8 +161,6 @@ module Concurrent
|
|
169
161
|
# @param [Hash] opts the options defining task execution.
|
170
162
|
# @option opts [Integer] :execution_interval number of seconds between
|
171
163
|
# task executions (default: EXECUTION_INTERVAL)
|
172
|
-
# @option opts [Integer] :timeout_interval number of seconds a task can
|
173
|
-
# run before it is considered to have failed (default: TIMEOUT_INTERVAL)
|
174
164
|
# @option opts [Boolean] :run_now Whether to run the task immediately
|
175
165
|
# upon instantiation or to wait until the first # execution_interval
|
176
166
|
# has passed (default: false)
|
@@ -256,18 +246,14 @@ module Concurrent
|
|
256
246
|
# @return [Fixnum] Number of seconds the task can run before it is
|
257
247
|
# considered to have failed.
|
258
248
|
def timeout_interval
|
259
|
-
|
249
|
+
warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly'
|
260
250
|
end
|
261
251
|
|
262
252
|
# @!attribute [rw] timeout_interval
|
263
253
|
# @return [Fixnum] Number of seconds the task can run before it is
|
264
254
|
# considered to have failed.
|
265
255
|
def timeout_interval=(value)
|
266
|
-
|
267
|
-
raise ArgumentError.new('must be greater than zero')
|
268
|
-
else
|
269
|
-
synchronize { @timeout_interval = value }
|
270
|
-
end
|
256
|
+
warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly'
|
271
257
|
end
|
272
258
|
|
273
259
|
private :post, :<<
|
@@ -278,7 +264,9 @@ module Concurrent
|
|
278
264
|
set_deref_options(opts)
|
279
265
|
|
280
266
|
self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
|
281
|
-
|
267
|
+
if opts[:timeout] || opts[:timeout_interval]
|
268
|
+
warn 'TimeTask timeouts are now ignored as these were not able to be implemented correctly'
|
269
|
+
end
|
282
270
|
@run_now = opts[:now] || opts[:run_now]
|
283
271
|
@executor = Concurrent::SafeTaskExecutor.new(task)
|
284
272
|
@running = Concurrent::AtomicBoolean.new(false)
|
@@ -308,7 +296,6 @@ module Concurrent
|
|
308
296
|
# @!visibility private
|
309
297
|
def execute_task(completion)
|
310
298
|
return nil unless @running.true?
|
311
|
-
ScheduledTask.execute(timeout_interval, args: [completion], &method(:timeout_task))
|
312
299
|
_success, value, reason = @executor.execute(self)
|
313
300
|
if completion.try?
|
314
301
|
self.value = value
|
@@ -320,15 +307,5 @@ module Concurrent
|
|
320
307
|
end
|
321
308
|
nil
|
322
309
|
end
|
323
|
-
|
324
|
-
# @!visibility private
|
325
|
-
def timeout_task(completion)
|
326
|
-
return unless @running.true?
|
327
|
-
if completion.try?
|
328
|
-
self.value = value
|
329
|
-
schedule_next_task
|
330
|
-
observers.notify_observers(Time.now, nil, Concurrent::TimeoutError.new)
|
331
|
-
end
|
332
|
-
end
|
333
310
|
end
|
334
311
|
end
|
File without changes
|
@@ -15,7 +15,6 @@ module Concurrent
|
|
15
15
|
# Create a new `TVar` with an initial value.
|
16
16
|
def initialize(value)
|
17
17
|
@value = value
|
18
|
-
@version = 0
|
19
18
|
@lock = Mutex.new
|
20
19
|
end
|
21
20
|
|
@@ -43,16 +42,6 @@ module Concurrent
|
|
43
42
|
@value = value
|
44
43
|
end
|
45
44
|
|
46
|
-
# @!visibility private
|
47
|
-
def unsafe_version # :nodoc:
|
48
|
-
@version
|
49
|
-
end
|
50
|
-
|
51
|
-
# @!visibility private
|
52
|
-
def unsafe_increment_version # :nodoc:
|
53
|
-
@version += 1
|
54
|
-
end
|
55
|
-
|
56
45
|
# @!visibility private
|
57
46
|
def unsafe_lock # :nodoc:
|
58
47
|
@lock
|
@@ -164,50 +153,39 @@ module Concurrent
|
|
164
153
|
|
165
154
|
ABORTED = ::Object.new
|
166
155
|
|
167
|
-
|
156
|
+
OpenEntry = Struct.new(:value, :modified)
|
168
157
|
|
169
158
|
AbortError = Class.new(StandardError)
|
170
159
|
LeaveError = Class.new(StandardError)
|
171
160
|
|
172
161
|
def initialize
|
173
|
-
@
|
174
|
-
@write_log = {}
|
162
|
+
@open_tvars = {}
|
175
163
|
end
|
176
164
|
|
177
165
|
def read(tvar)
|
178
|
-
|
179
|
-
|
180
|
-
if @write_log.has_key? tvar
|
181
|
-
@write_log[tvar]
|
182
|
-
else
|
183
|
-
@read_log.push(ReadLogEntry.new(tvar, tvar.unsafe_version))
|
184
|
-
tvar.unsafe_value
|
185
|
-
end
|
166
|
+
entry = open(tvar)
|
167
|
+
entry.value
|
186
168
|
end
|
187
169
|
|
188
170
|
def write(tvar, value)
|
189
|
-
|
171
|
+
entry = open(tvar)
|
172
|
+
entry.modified = true
|
173
|
+
entry.value = value
|
174
|
+
end
|
190
175
|
|
191
|
-
|
192
|
-
|
176
|
+
def open(tvar)
|
177
|
+
entry = @open_tvars[tvar]
|
193
178
|
|
179
|
+
unless entry
|
194
180
|
unless tvar.unsafe_lock.try_lock
|
195
|
-
# Someone else is writing to this TVar - abort
|
196
181
|
Concurrent::abort_transaction
|
197
182
|
end
|
198
183
|
|
199
|
-
|
200
|
-
|
201
|
-
@read_log.each do |log_entry|
|
202
|
-
if log_entry.tvar == tvar and tvar.unsafe_version > log_entry.version
|
203
|
-
Concurrent::abort_transaction
|
204
|
-
end
|
205
|
-
end
|
184
|
+
entry = OpenEntry.new(tvar.unsafe_value, false)
|
185
|
+
@open_tvars[tvar] = entry
|
206
186
|
end
|
207
187
|
|
208
|
-
|
209
|
-
|
210
|
-
@write_log[tvar] = value
|
188
|
+
entry
|
211
189
|
end
|
212
190
|
|
213
191
|
def abort
|
@@ -215,32 +193,17 @@ module Concurrent
|
|
215
193
|
end
|
216
194
|
|
217
195
|
def commit
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
tvar.unsafe_value = value
|
222
|
-
tvar.unsafe_increment_version
|
223
|
-
end
|
224
|
-
|
225
|
-
unlock
|
226
|
-
|
227
|
-
true
|
228
|
-
end
|
229
|
-
|
230
|
-
def valid?
|
231
|
-
@read_log.each do |log_entry|
|
232
|
-
unless @write_log.has_key? log_entry.tvar
|
233
|
-
if log_entry.tvar.unsafe_version > log_entry.version
|
234
|
-
return false
|
235
|
-
end
|
196
|
+
@open_tvars.each do |tvar, entry|
|
197
|
+
if entry.modified
|
198
|
+
tvar.unsafe_value = entry.value
|
236
199
|
end
|
237
200
|
end
|
238
201
|
|
239
|
-
|
202
|
+
unlock
|
240
203
|
end
|
241
204
|
|
242
205
|
def unlock
|
243
|
-
@
|
206
|
+
@open_tvars.each_key do |tvar|
|
244
207
|
tvar.unsafe_lock.unlock
|
245
208
|
end
|
246
209
|
end
|
File without changes
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'concurrent/synchronization'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# @!macro monotonic_get_time
|
6
|
+
#
|
7
|
+
# Returns the current time a tracked by the application monotonic clock.
|
8
|
+
#
|
9
|
+
# @param [Symbol] unit the time unit to be returned, can be either
|
10
|
+
# :float_second, :float_millisecond, :float_microsecond, :second,
|
11
|
+
# :millisecond, :microsecond, or :nanosecond default to :float_second.
|
12
|
+
#
|
13
|
+
# @return [Float] The current monotonic time since some unspecified
|
14
|
+
# starting point
|
15
|
+
#
|
16
|
+
# @!macro monotonic_clock_warning
|
17
|
+
if defined?(Process::CLOCK_MONOTONIC)
|
18
|
+
|
19
|
+
def monotonic_time(unit = :float_second)
|
20
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
|
21
|
+
end
|
22
|
+
|
23
|
+
elsif Concurrent.on_jruby?
|
24
|
+
|
25
|
+
# @!visibility private
|
26
|
+
TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
|
27
|
+
TIME_UNITS.merge!(
|
28
|
+
second: 1_000_000_000,
|
29
|
+
millisecond: 1_000_000,
|
30
|
+
microsecond: 1_000,
|
31
|
+
nanosecond: 1,
|
32
|
+
float_second: 1_000_000_000.0,
|
33
|
+
float_millisecond: 1_000_000.0,
|
34
|
+
float_microsecond: 1_000.0,
|
35
|
+
)
|
36
|
+
TIME_UNITS.freeze
|
37
|
+
private_constant :TIME_UNITS
|
38
|
+
|
39
|
+
def monotonic_time(unit = :float_second)
|
40
|
+
java.lang.System.nanoTime() / TIME_UNITS[unit]
|
41
|
+
end
|
42
|
+
|
43
|
+
else
|
44
|
+
|
45
|
+
class_definition = Class.new(Synchronization::LockableObject) do
|
46
|
+
def initialize
|
47
|
+
@last_time = Time.now.to_f
|
48
|
+
@time_units = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
|
49
|
+
@time_units.merge!(
|
50
|
+
second: [nil, true],
|
51
|
+
millisecond: [1_000, true],
|
52
|
+
microsecond: [1_000_000, true],
|
53
|
+
nanosecond: [1_000_000_000, true],
|
54
|
+
float_second: [nil, false],
|
55
|
+
float_millisecond: [1_000.0, false],
|
56
|
+
float_microsecond: [1_000_000.0, false],
|
57
|
+
)
|
58
|
+
super()
|
59
|
+
end
|
60
|
+
|
61
|
+
# @!visibility private
|
62
|
+
def get_time(unit)
|
63
|
+
synchronize do
|
64
|
+
now = Time.now.to_f
|
65
|
+
if @last_time < now
|
66
|
+
@last_time = now
|
67
|
+
else # clock has moved back in time
|
68
|
+
@last_time += 0.000_001
|
69
|
+
end
|
70
|
+
scale, to_int = @time_units[unit]
|
71
|
+
now *= scale if scale
|
72
|
+
now = now.to_i if to_int
|
73
|
+
now
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Clock that cannot be set and represents monotonic time since
|
79
|
+
# some unspecified starting point.
|
80
|
+
#
|
81
|
+
# @!visibility private
|
82
|
+
GLOBAL_MONOTONIC_CLOCK = class_definition.new
|
83
|
+
private_constant :GLOBAL_MONOTONIC_CLOCK
|
84
|
+
|
85
|
+
def monotonic_time(unit = :float_second)
|
86
|
+
GLOBAL_MONOTONIC_CLOCK.get_time(unit)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
module_function :monotonic_time
|
90
|
+
end
|
File without changes
|
File without changes
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'etc'
|
1
2
|
require 'rbconfig'
|
2
3
|
require 'concurrent/delay'
|
3
4
|
|
@@ -22,6 +23,8 @@ module Concurrent
|
|
22
23
|
# occasionally poll this property." Subsequently the result will NOT be
|
23
24
|
# memoized under JRuby.
|
24
25
|
#
|
26
|
+
# Ruby's Etc.nprocessors will be used if available (MRI 2.2+).
|
27
|
+
#
|
25
28
|
# On Windows the Win32 API will be queried for the
|
26
29
|
# `NumberOfLogicalProcessors from Win32_Processor`. This will return the
|
27
30
|
# total number "logical processors for the current instance of the
|
@@ -77,44 +80,13 @@ module Concurrent
|
|
77
80
|
if Concurrent.on_jruby?
|
78
81
|
java.lang.Runtime.getRuntime.availableProcessors
|
79
82
|
else
|
80
|
-
|
81
|
-
if os_name =~ /mingw|mswin/
|
82
|
-
require 'win32ole'
|
83
|
-
result = WIN32OLE.connect("winmgmts://").ExecQuery(
|
84
|
-
"select NumberOfLogicalProcessors from Win32_Processor")
|
85
|
-
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
|
86
|
-
elsif File.readable?("/proc/cpuinfo") && (cpuinfo_count = IO.read("/proc/cpuinfo").scan(/^processor/).size) > 0
|
87
|
-
cpuinfo_count
|
88
|
-
elsif File.executable?("/usr/bin/nproc")
|
89
|
-
IO.popen("/usr/bin/nproc --all", &:read).to_i
|
90
|
-
elsif File.executable?("/usr/bin/hwprefs")
|
91
|
-
IO.popen("/usr/bin/hwprefs thread_count", &:read).to_i
|
92
|
-
elsif File.executable?("/usr/sbin/psrinfo")
|
93
|
-
IO.popen("/usr/sbin/psrinfo", &:read).scan(/^.*on-*line/).size
|
94
|
-
elsif File.executable?("/usr/sbin/ioscan")
|
95
|
-
IO.popen("/usr/sbin/ioscan -kC processor", &:read).scan(/^.*processor/).size
|
96
|
-
elsif File.executable?("/usr/sbin/pmcycles")
|
97
|
-
IO.popen("/usr/sbin/pmcycles -m", &:read).count("\n")
|
98
|
-
elsif File.executable?("/usr/sbin/lsdev")
|
99
|
-
IO.popen("/usr/sbin/lsdev -Cc processor -S 1", &:read).count("\n")
|
100
|
-
elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
|
101
|
-
IO.popen("/usr/sbin/sysconf NPROC_ONLN", &:read).to_i
|
102
|
-
elsif File.executable?("/usr/sbin/sysctl")
|
103
|
-
IO.popen("/usr/sbin/sysctl -n hw.ncpu", &:read).to_i
|
104
|
-
elsif File.executable?("/sbin/sysctl")
|
105
|
-
IO.popen("/sbin/sysctl -n hw.ncpu", &:read).to_i
|
106
|
-
else
|
107
|
-
# TODO (pitr-ch 05-Nov-2016): warn about failures
|
108
|
-
1
|
109
|
-
end
|
83
|
+
Etc.nprocessors
|
110
84
|
end
|
111
|
-
rescue
|
112
|
-
return 1
|
113
85
|
end
|
114
86
|
|
115
87
|
def compute_physical_processor_count
|
116
88
|
ppc = case RbConfig::CONFIG["target_os"]
|
117
|
-
when /
|
89
|
+
when /darwin\d\d/
|
118
90
|
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu", &:read).to_i
|
119
91
|
when /linux/
|
120
92
|
cores = {} # unique physical ID / core ID combinations
|
File without changes
|