concurrent-ruby 1.1.8 → 1.2.0
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 +36 -0
- data/Gemfile +2 -8
- data/README.md +49 -28
- data/Rakefile +59 -75
- 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/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
- data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
- data/lib/concurrent-ruby/concurrent/array.rb +0 -10
- data/lib/concurrent-ruby/concurrent/async.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +82 -151
- data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/event.rb +3 -3
- data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
- data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/locals.rb +188 -0
- data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +19 -3
- data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
- data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +9 -9
- data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +32 -14
- data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
- data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
- data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
- data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
- data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +11 -1
- data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
- data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
- data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
- data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +17 -14
- data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +13 -3
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +3 -3
- data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +4 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +10 -4
- data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +26 -37
- data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +6 -6
- data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
- data/lib/concurrent-ruby/concurrent/hash.rb +0 -9
- data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
- data/lib/concurrent-ruby/concurrent/map.rb +18 -8
- data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
- data/lib/concurrent-ruby/concurrent/promise.rb +2 -1
- data/lib/concurrent-ruby/concurrent/promises.rb +7 -6
- data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
- data/lib/concurrent-ruby/concurrent/scheduled_task.rb +30 -17
- data/lib/concurrent-ruby/concurrent/set.rb +12 -14
- data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
- data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
- data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +6 -5
- data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +18 -5
- data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
- data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
- data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
- data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +2 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +16 -27
- data/lib/concurrent-ruby/concurrent/timer_task.rb +11 -33
- data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
- data/lib/concurrent-ruby/concurrent/tvar.rb +22 -61
- data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +7 -46
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
- data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +36 -89
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- data/lib/concurrent-ruby/concurrent-ruby.rb +5 -1
- metadata +11 -12
- data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
- data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
- data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
- data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -65
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'concurrent/errors'
|
2
2
|
require 'concurrent/concern/deprecation'
|
3
3
|
require 'concurrent/executor/executor_service'
|
4
|
-
require 'concurrent/synchronization'
|
4
|
+
require 'concurrent/synchronization/lockable_object'
|
5
5
|
|
6
6
|
module Concurrent
|
7
7
|
|
@@ -75,28 +75,31 @@ module Concurrent
|
|
75
75
|
|
76
76
|
private
|
77
77
|
|
78
|
-
#
|
79
|
-
# reaches `max_queue`.
|
78
|
+
# Returns an action which executes the `fallback_policy` once the queue
|
79
|
+
# size reaches `max_queue`. The reason for the indirection of an action
|
80
|
+
# is so that the work can be deferred outside of synchronization.
|
80
81
|
#
|
81
82
|
# @param [Array] args the arguments to the task which is being handled.
|
82
83
|
#
|
83
84
|
# @!visibility private
|
84
|
-
def
|
85
|
+
def fallback_action(*args)
|
85
86
|
case fallback_policy
|
86
87
|
when :abort
|
87
|
-
raise RejectedExecutionError
|
88
|
+
lambda { raise RejectedExecutionError }
|
88
89
|
when :discard
|
89
|
-
false
|
90
|
+
lambda { false }
|
90
91
|
when :caller_runs
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
92
|
+
lambda {
|
93
|
+
begin
|
94
|
+
yield(*args)
|
95
|
+
rescue => ex
|
96
|
+
# let it fail
|
97
|
+
log DEBUG, ex
|
98
|
+
end
|
99
|
+
true
|
100
|
+
}
|
98
101
|
else
|
99
|
-
fail "Unknown fallback policy #{fallback_policy}"
|
102
|
+
lambda { fail "Unknown fallback policy #{fallback_policy}" }
|
100
103
|
end
|
101
104
|
end
|
102
105
|
|
@@ -71,9 +71,16 @@ module Concurrent
|
|
71
71
|
# @return [Integer] Number of tasks that may be enqueued before reaching `max_queue` and rejecting
|
72
72
|
# new tasks. A value of -1 indicates that the queue may grow without bound.
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
# @!macro thread_pool_executor_method_prune_pool
|
75
|
+
# Prune the thread pool of unneeded threads
|
76
|
+
#
|
77
|
+
# What is being pruned is controlled by the min_threads and idletime
|
78
|
+
# parameters passed at pool creation time
|
79
|
+
#
|
80
|
+
# This is a no-op on some pool implementation (e.g. the Java one). The Ruby
|
81
|
+
# pool will auto-prune each time a new job is posted. You will need to call
|
82
|
+
# this method explicitely in case your application post jobs in bursts (a
|
83
|
+
# lot of jobs and then nothing for long periods)
|
77
84
|
|
78
85
|
# @!macro thread_pool_executor_public_api
|
79
86
|
#
|
@@ -111,6 +118,9 @@ module Concurrent
|
|
111
118
|
#
|
112
119
|
# @!method can_overflow?
|
113
120
|
# @!macro executor_service_method_can_overflow_question
|
121
|
+
#
|
122
|
+
# @!method prune_pool
|
123
|
+
# @!macro thread_pool_executor_method_prune_pool
|
114
124
|
|
115
125
|
|
116
126
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
1
|
+
require 'concurrent/utility/engine'
|
2
2
|
|
3
|
+
if Concurrent.on_jruby?
|
3
4
|
require 'concurrent/errors'
|
4
|
-
require 'concurrent/utility/engine'
|
5
5
|
require 'concurrent/executor/abstract_executor_service'
|
6
6
|
|
7
7
|
module Concurrent
|
@@ -20,7 +20,7 @@ if Concurrent.on_jruby?
|
|
20
20
|
|
21
21
|
def post(*args, &task)
|
22
22
|
raise ArgumentError.new('no block given') unless block_given?
|
23
|
-
return
|
23
|
+
return fallback_action(*args, &task).call unless running?
|
24
24
|
@executor.submit Job.new(args, task)
|
25
25
|
true
|
26
26
|
rescue Java::JavaUtilConcurrent::RejectedExecutionException
|
@@ -16,10 +16,16 @@ module Concurrent
|
|
16
16
|
|
17
17
|
def post(*args, &task)
|
18
18
|
raise ArgumentError.new('no block given') unless block_given?
|
19
|
-
synchronize
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
deferred_action = synchronize {
|
20
|
+
if running?
|
21
|
+
ns_execute(*args, &task)
|
22
|
+
else
|
23
|
+
fallback_action(*args, &task)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
if deferred_action
|
27
|
+
deferred_action.call
|
28
|
+
else
|
23
29
|
true
|
24
30
|
end
|
25
31
|
end
|
@@ -93,13 +93,8 @@ module Concurrent
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# @!visibility private
|
96
|
-
def ready_worker(worker)
|
97
|
-
synchronize { ns_ready_worker worker }
|
98
|
-
end
|
99
|
-
|
100
|
-
# @!visibility private
|
101
|
-
def worker_not_old_enough(worker)
|
102
|
-
synchronize { ns_worker_not_old_enough worker }
|
96
|
+
def ready_worker(worker, last_message)
|
97
|
+
synchronize { ns_ready_worker worker, last_message }
|
103
98
|
end
|
104
99
|
|
105
100
|
# @!visibility private
|
@@ -112,6 +107,11 @@ module Concurrent
|
|
112
107
|
synchronize { @completed_task_count += 1 }
|
113
108
|
end
|
114
109
|
|
110
|
+
# @!macro thread_pool_executor_method_prune_pool
|
111
|
+
def prune_pool
|
112
|
+
synchronize { ns_prune_pool }
|
113
|
+
end
|
114
|
+
|
115
115
|
private
|
116
116
|
|
117
117
|
# @!visibility private
|
@@ -156,10 +156,11 @@ module Concurrent
|
|
156
156
|
if ns_assign_worker(*args, &task) || ns_enqueue(*args, &task)
|
157
157
|
@scheduled_task_count += 1
|
158
158
|
else
|
159
|
-
|
159
|
+
return fallback_action(*args, &task)
|
160
160
|
end
|
161
161
|
|
162
162
|
ns_prune_pool if @next_gc_time < Concurrent.monotonic_time
|
163
|
+
nil
|
163
164
|
end
|
164
165
|
|
165
166
|
# @!visibility private
|
@@ -192,7 +193,7 @@ module Concurrent
|
|
192
193
|
# @!visibility private
|
193
194
|
def ns_assign_worker(*args, &task)
|
194
195
|
# keep growing if the pool is not at the minimum yet
|
195
|
-
worker = (@ready.pop if @pool.size >= @min_length) || ns_add_busy_worker
|
196
|
+
worker, _ = (@ready.pop if @pool.size >= @min_length) || ns_add_busy_worker
|
196
197
|
if worker
|
197
198
|
worker << [task, args]
|
198
199
|
true
|
@@ -223,7 +224,7 @@ module Concurrent
|
|
223
224
|
def ns_worker_died(worker)
|
224
225
|
ns_remove_busy_worker worker
|
225
226
|
replacement_worker = ns_add_busy_worker
|
226
|
-
ns_ready_worker replacement_worker, false if replacement_worker
|
227
|
+
ns_ready_worker replacement_worker, Concurrent.monotonic_time, false if replacement_worker
|
227
228
|
end
|
228
229
|
|
229
230
|
# creates new worker which has to receive work to do after it's added
|
@@ -242,29 +243,21 @@ module Concurrent
|
|
242
243
|
# handle ready worker, giving it new job or assigning back to @ready
|
243
244
|
#
|
244
245
|
# @!visibility private
|
245
|
-
def ns_ready_worker(worker, success = true)
|
246
|
+
def ns_ready_worker(worker, last_message, success = true)
|
246
247
|
task_and_args = @queue.shift
|
247
248
|
if task_and_args
|
248
249
|
worker << task_and_args
|
249
250
|
else
|
250
251
|
# stop workers when !running?, do not return them to @ready
|
251
252
|
if running?
|
252
|
-
|
253
|
+
raise unless last_message
|
254
|
+
@ready.push([worker, last_message])
|
253
255
|
else
|
254
256
|
worker.stop
|
255
257
|
end
|
256
258
|
end
|
257
259
|
end
|
258
260
|
|
259
|
-
# returns back worker to @ready which was not idle for enough time
|
260
|
-
#
|
261
|
-
# @!visibility private
|
262
|
-
def ns_worker_not_old_enough(worker)
|
263
|
-
# let's put workers coming from idle_test back to the start (as the oldest worker)
|
264
|
-
@ready.unshift(worker)
|
265
|
-
true
|
266
|
-
end
|
267
|
-
|
268
261
|
# removes a worker which is not in not tracked in @ready
|
269
262
|
#
|
270
263
|
# @!visibility private
|
@@ -278,10 +271,17 @@ module Concurrent
|
|
278
271
|
#
|
279
272
|
# @!visibility private
|
280
273
|
def ns_prune_pool
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
274
|
+
now = Concurrent.monotonic_time
|
275
|
+
stopped_workers = 0
|
276
|
+
while !@ready.empty? && (@pool.size - stopped_workers > @min_length)
|
277
|
+
worker, last_message = @ready.first
|
278
|
+
if now - last_message > self.idletime
|
279
|
+
stopped_workers += 1
|
280
|
+
@ready.shift
|
281
|
+
worker << :stop
|
282
|
+
else break
|
283
|
+
end
|
284
|
+
end
|
285
285
|
|
286
286
|
@next_gc_time = Concurrent.monotonic_time + @gc_interval
|
287
287
|
end
|
@@ -330,19 +330,10 @@ module Concurrent
|
|
330
330
|
|
331
331
|
def create_worker(queue, pool, idletime)
|
332
332
|
Thread.new(queue, pool, idletime) do |my_queue, my_pool, my_idletime|
|
333
|
-
last_message = Concurrent.monotonic_time
|
334
333
|
catch(:stop) do
|
335
334
|
loop do
|
336
335
|
|
337
336
|
case message = my_queue.pop
|
338
|
-
when :idle_test
|
339
|
-
if (Concurrent.monotonic_time - last_message) > my_idletime
|
340
|
-
my_pool.remove_busy_worker(self)
|
341
|
-
throw :stop
|
342
|
-
else
|
343
|
-
my_pool.worker_not_old_enough(self)
|
344
|
-
end
|
345
|
-
|
346
337
|
when :stop
|
347
338
|
my_pool.remove_busy_worker(self)
|
348
339
|
throw :stop
|
@@ -350,9 +341,7 @@ module Concurrent
|
|
350
341
|
else
|
351
342
|
task, args = message
|
352
343
|
run_task my_pool, task, args
|
353
|
-
|
354
|
-
|
355
|
-
my_pool.ready_worker(self)
|
344
|
+
my_pool.ready_worker(self, Concurrent.monotonic_time)
|
356
345
|
end
|
357
346
|
end
|
358
347
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
1
|
+
require 'concurrent/synchronization/lockable_object'
|
2
2
|
|
3
3
|
module Concurrent
|
4
4
|
|
@@ -16,10 +16,10 @@ module Concurrent
|
|
16
16
|
|
17
17
|
# @return [Array]
|
18
18
|
def execute(*args)
|
19
|
-
|
20
|
-
|
21
|
-
value = reason = nil
|
19
|
+
success = true
|
20
|
+
value = reason = nil
|
22
21
|
|
22
|
+
synchronize do
|
23
23
|
begin
|
24
24
|
value = @task.call(*args)
|
25
25
|
success = true
|
@@ -27,9 +27,9 @@ module Concurrent
|
|
27
27
|
reason = ex
|
28
28
|
success = false
|
29
29
|
end
|
30
|
-
|
31
|
-
[success, value, reason]
|
32
30
|
end
|
31
|
+
|
32
|
+
[success, value, reason]
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -1,5 +1,8 @@
|
|
1
|
-
require 'concurrent/
|
1
|
+
require 'concurrent/atomic/atomic_boolean'
|
2
|
+
require 'concurrent/atomic/atomic_fixnum'
|
3
|
+
require 'concurrent/atomic/event'
|
2
4
|
require 'concurrent/executor/executor_service'
|
5
|
+
require 'concurrent/executor/ruby_executor_service'
|
3
6
|
|
4
7
|
module Concurrent
|
5
8
|
|
@@ -28,15 +28,6 @@ module Concurrent
|
|
28
28
|
end
|
29
29
|
JRubyHash
|
30
30
|
|
31
|
-
when Concurrent.on_rbx?
|
32
|
-
require 'monitor'
|
33
|
-
require 'concurrent/thread_safe/util/data_structures'
|
34
|
-
|
35
|
-
class RbxHash < ::Hash
|
36
|
-
end
|
37
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxHash
|
38
|
-
RbxHash
|
39
|
-
|
40
31
|
when Concurrent.on_truffleruby?
|
41
32
|
require 'concurrent/thread_safe/util/data_structures'
|
42
33
|
|
@@ -3,7 +3,8 @@ require 'concurrent/errors'
|
|
3
3
|
require 'concurrent/collection/copy_on_write_observer_set'
|
4
4
|
require 'concurrent/concern/obligation'
|
5
5
|
require 'concurrent/concern/observable'
|
6
|
-
require 'concurrent/
|
6
|
+
require 'concurrent/executor/safe_task_executor'
|
7
|
+
require 'concurrent/synchronization/lockable_object'
|
7
8
|
|
8
9
|
module Concurrent
|
9
10
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/constants'
|
3
|
-
require 'concurrent/synchronization'
|
4
3
|
require 'concurrent/utility/engine'
|
5
4
|
|
6
5
|
module Concurrent
|
@@ -10,14 +9,20 @@ module Concurrent
|
|
10
9
|
# @!visibility private
|
11
10
|
MapImplementation = case
|
12
11
|
when Concurrent.on_jruby?
|
12
|
+
require 'concurrent/utility/native_extension_loader'
|
13
13
|
# noinspection RubyResolve
|
14
14
|
JRubyMapBackend
|
15
15
|
when Concurrent.on_cruby?
|
16
16
|
require 'concurrent/collection/map/mri_map_backend'
|
17
17
|
MriMapBackend
|
18
|
-
when Concurrent.
|
19
|
-
|
20
|
-
|
18
|
+
when Concurrent.on_truffleruby?
|
19
|
+
if defined?(::TruffleRuby::ConcurrentMap)
|
20
|
+
require 'concurrent/collection/map/truffleruby_map_backend'
|
21
|
+
TruffleRubyMapBackend
|
22
|
+
else
|
23
|
+
require 'concurrent/collection/map/atomic_reference_map_backend'
|
24
|
+
AtomicReferenceMapBackend
|
25
|
+
end
|
21
26
|
else
|
22
27
|
warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation'
|
23
28
|
require 'concurrent/collection/map/synchronized_map_backend'
|
@@ -114,7 +119,7 @@ module Concurrent
|
|
114
119
|
# @return [true, false] true if deleted
|
115
120
|
# @!macro map.atomic_method
|
116
121
|
|
117
|
-
|
122
|
+
#
|
118
123
|
def initialize(options = nil, &block)
|
119
124
|
if options.kind_of?(::Hash)
|
120
125
|
validate_options_hash!(options)
|
@@ -143,8 +148,15 @@ module Concurrent
|
|
143
148
|
end
|
144
149
|
end
|
145
150
|
|
151
|
+
# Set a value with key
|
152
|
+
# @param [Object] key
|
153
|
+
# @param [Object] value
|
154
|
+
# @return [Object] the new value
|
155
|
+
def []=(key, value)
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
146
159
|
alias_method :get, :[]
|
147
|
-
# TODO (pitr-ch 30-Oct-2018): doc
|
148
160
|
alias_method :put, :[]=
|
149
161
|
|
150
162
|
# Get a value with key, or default_value when key is absent,
|
@@ -187,7 +199,6 @@ module Concurrent
|
|
187
199
|
# @yieldparam key [Object]
|
188
200
|
# @yieldreturn [Object] default value
|
189
201
|
# @return [Object] the value or default value
|
190
|
-
# @!macro map.atomic_method_with_block
|
191
202
|
def fetch_or_store(key, default_value = NULL)
|
192
203
|
fetch(key) do
|
193
204
|
put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
|
@@ -271,7 +282,6 @@ module Concurrent
|
|
271
282
|
each_pair { |k, v| return k if v == value }
|
272
283
|
nil
|
273
284
|
end unless method_defined?(:key)
|
274
|
-
alias_method :index, :key if RUBY_VERSION < '1.9'
|
275
285
|
|
276
286
|
# Is map empty?
|
277
287
|
# @return [true, false]
|
@@ -66,7 +66,7 @@ module Concurrent
|
|
66
66
|
# Start by requiring promises
|
67
67
|
#
|
68
68
|
# ```ruby
|
69
|
-
# require 'concurrent'
|
69
|
+
# require 'concurrent/promise'
|
70
70
|
# ```
|
71
71
|
#
|
72
72
|
# Then create one
|
@@ -250,6 +250,7 @@ module Concurrent
|
|
250
250
|
realize(@promise_body)
|
251
251
|
end
|
252
252
|
else
|
253
|
+
compare_and_set_state(:pending, :unscheduled)
|
253
254
|
@parent.execute
|
254
255
|
end
|
255
256
|
self
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
1
|
+
require 'concurrent/synchronization/object'
|
2
2
|
require 'concurrent/atomic/atomic_boolean'
|
3
3
|
require 'concurrent/atomic/atomic_fixnum'
|
4
4
|
require 'concurrent/collection/lock_free_stack'
|
5
|
+
require 'concurrent/configuration'
|
5
6
|
require 'concurrent/errors'
|
6
7
|
require 'concurrent/re_include'
|
7
8
|
|
@@ -313,7 +314,7 @@ module Concurrent
|
|
313
314
|
end
|
314
315
|
|
315
316
|
# @!macro promises.shortcut.on
|
316
|
-
# @return [
|
317
|
+
# @return [Event]
|
317
318
|
def any_event(*futures_and_or_events)
|
318
319
|
any_event_on default_executor, *futures_and_or_events
|
319
320
|
end
|
@@ -892,7 +893,7 @@ module Concurrent
|
|
892
893
|
private
|
893
894
|
|
894
895
|
def rejected_resolution(raise_on_reassign, state)
|
895
|
-
Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
|
+
raise Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
897
|
return false
|
897
898
|
end
|
898
899
|
|
@@ -1298,7 +1299,7 @@ module Concurrent
|
|
1298
1299
|
|
1299
1300
|
# @!macro promise.param.raise_on_reassign
|
1300
1301
|
# @param [Boolean] raise_on_reassign should method raise exception if already resolved
|
1301
|
-
# @return [self, false] false is
|
1302
|
+
# @return [self, false] false is returned when raise_on_reassign is false and the receiver
|
1302
1303
|
# is already resolved.
|
1303
1304
|
#
|
1304
1305
|
|
@@ -2074,8 +2075,8 @@ module Concurrent
|
|
2074
2075
|
|
2075
2076
|
private
|
2076
2077
|
|
2077
|
-
def resolvable?(countdown,
|
2078
|
-
|
2078
|
+
def resolvable?(countdown, event_or_future, index)
|
2079
|
+
(event_or_future.is_a?(Event) ? event_or_future.resolved? : event_or_future.fulfilled?) ||
|
2079
2080
|
# inlined super from BlockedPromise
|
2080
2081
|
countdown.zero?
|
2081
2082
|
end
|
@@ -57,30 +57,43 @@ module Concurrent
|
|
57
57
|
#
|
58
58
|
# @example Basic usage
|
59
59
|
#
|
60
|
-
# require 'concurrent'
|
61
|
-
# require '
|
62
|
-
# require 'open-uri'
|
60
|
+
# require 'concurrent/scheduled_task'
|
61
|
+
# require 'csv'
|
62
|
+
# require 'open-uri'
|
63
63
|
#
|
64
64
|
# class Ticker
|
65
|
-
# def get_year_end_closing(symbol, year)
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
65
|
+
# def get_year_end_closing(symbol, year, api_key)
|
66
|
+
# uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
|
67
|
+
# data = []
|
68
|
+
# csv = URI.parse(uri).read
|
69
|
+
# if csv.include?('call frequency')
|
70
|
+
# return :rate_limit_exceeded
|
71
|
+
# end
|
72
|
+
# CSV.parse(csv, headers: true) do |row|
|
73
|
+
# data << row['close'].to_f if row['timestamp'].include?(year.to_s)
|
74
|
+
# end
|
75
|
+
# year_end = data.first
|
76
|
+
# year_end
|
77
|
+
# rescue => e
|
78
|
+
# p e
|
79
|
+
# end
|
70
80
|
# end
|
71
81
|
#
|
82
|
+
# api_key = ENV['ALPHAVANTAGE_KEY']
|
83
|
+
# abort(error_message) unless api_key
|
84
|
+
#
|
72
85
|
# # Future
|
73
|
-
# price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013) }
|
86
|
+
# price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) }
|
74
87
|
# price.state #=> :pending
|
75
|
-
#
|
76
|
-
# price.value #=>
|
77
|
-
# price.state #=> :fulfilled
|
88
|
+
# price.pending? #=> true
|
89
|
+
# price.value(0) #=> nil (does not block)
|
78
90
|
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
91
|
+
# sleep(1) # do other stuff
|
92
|
+
#
|
93
|
+
# price.value #=> 63.65 (after blocking if necessary)
|
94
|
+
# price.state #=> :fulfilled
|
95
|
+
# price.fulfilled? #=> true
|
96
|
+
# price.value #=> 63.65
|
84
97
|
#
|
85
98
|
# @example Successful task execution
|
86
99
|
#
|
@@ -19,13 +19,19 @@ module Concurrent
|
|
19
19
|
#
|
20
20
|
# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set`
|
21
21
|
|
22
|
-
|
23
22
|
# @!macro internal_implementation_note
|
24
23
|
SetImplementation = case
|
25
24
|
when Concurrent.on_cruby?
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
25
|
+
# The CRuby implementation of Set is written in Ruby itself and is
|
26
|
+
# not thread safe for certain methods.
|
27
|
+
require 'monitor'
|
28
|
+
require 'concurrent/thread_safe/util/data_structures'
|
29
|
+
|
30
|
+
class CRubySet < ::Set
|
31
|
+
end
|
32
|
+
|
33
|
+
ThreadSafe::Util.make_synchronized_on_cruby CRubySet
|
34
|
+
CRubySet
|
29
35
|
|
30
36
|
when Concurrent.on_jruby?
|
31
37
|
require 'jruby/synchronized'
|
@@ -33,16 +39,8 @@ module Concurrent
|
|
33
39
|
class JRubySet < ::Set
|
34
40
|
include JRuby::Synchronized
|
35
41
|
end
|
36
|
-
JRubySet
|
37
|
-
|
38
|
-
when Concurrent.on_rbx?
|
39
|
-
require 'monitor'
|
40
|
-
require 'concurrent/thread_safe/util/data_structures'
|
41
42
|
|
42
|
-
|
43
|
-
end
|
44
|
-
ThreadSafe::Util.make_synchronized_on_rbx Concurrent::RbxSet
|
45
|
-
RbxSet
|
43
|
+
JRubySet
|
46
44
|
|
47
45
|
when Concurrent.on_truffleruby?
|
48
46
|
require 'concurrent/thread_safe/util/data_structures'
|
@@ -50,7 +48,7 @@ module Concurrent
|
|
50
48
|
class TruffleRubySet < ::Set
|
51
49
|
end
|
52
50
|
|
53
|
-
ThreadSafe::Util.make_synchronized_on_truffleruby
|
51
|
+
ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubySet
|
54
52
|
TruffleRubySet
|
55
53
|
|
56
54
|
else
|