concurrent-ruby 0.7.0.rc2-java → 0.7.1-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.
- data/CHANGELOG.md +138 -0
- data/README.md +108 -95
- data/lib/concurrent/actor.rb +12 -13
- data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +1 -1
- data/lib/concurrent/actor/behaviour/executes_context.rb +1 -1
- data/lib/concurrent/actor/behaviour/linking.rb +4 -1
- data/lib/concurrent/actor/behaviour/pausing.rb +2 -2
- data/lib/concurrent/actor/behaviour/supervised.rb +3 -2
- data/lib/concurrent/actor/behaviour/terminates_children.rb +1 -1
- data/lib/concurrent/actor/behaviour/termination.rb +1 -1
- data/lib/concurrent/actor/context.rb +2 -1
- data/lib/concurrent/actor/core.rb +8 -4
- data/lib/concurrent/actor/utils.rb +10 -0
- data/lib/concurrent/actor/utils/ad_hoc.rb +21 -0
- data/lib/concurrent/actor/utils/balancer.rb +42 -0
- data/lib/concurrent/actor/utils/broadcast.rb +22 -6
- data/lib/concurrent/actor/utils/pool.rb +59 -0
- data/lib/concurrent/agent.rb +1 -22
- data/lib/concurrent/async.rb +1 -79
- data/lib/concurrent/atomic.rb +20 -26
- data/lib/concurrent/atomic/atomic_boolean.rb +4 -1
- data/lib/concurrent/atomic/atomic_fixnum.rb +4 -1
- data/lib/concurrent/atomic/thread_local_var.rb +71 -24
- data/lib/concurrent/atomic_reference/jruby.rb +10 -6
- data/lib/concurrent/atomic_reference/ruby.rb +14 -10
- data/lib/concurrent/atomics.rb +0 -1
- data/lib/concurrent/configuration.rb +11 -5
- data/lib/concurrent/dataflow.rb +1 -30
- data/lib/concurrent/dereferenceable.rb +9 -2
- data/lib/concurrent/executor/indirect_immediate_executor.rb +46 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +2 -4
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +24 -22
- data/lib/concurrent/executor/serialized_execution.rb +36 -23
- data/lib/concurrent/executor/thread_pool_executor.rb +2 -0
- data/lib/concurrent/executor/timer_set.rb +7 -8
- data/lib/concurrent/executors.rb +1 -0
- data/lib/concurrent/future.rb +7 -29
- data/lib/concurrent/ivar.rb +9 -0
- data/lib/concurrent/logging.rb +3 -0
- data/lib/concurrent/mvar.rb +26 -9
- data/lib/concurrent/observable.rb +33 -0
- data/lib/concurrent/promise.rb +59 -1
- data/lib/concurrent/scheduled_task.rb +1 -0
- data/lib/concurrent/timer_task.rb +18 -18
- data/lib/concurrent/tvar.rb +3 -1
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.jar +0 -0
- data/lib/concurrent_ruby_ext.so +0 -0
- data/lib/extension_helper.rb +25 -6
- metadata +15 -7
- data/lib/concurrent/actor/ad_hoc.rb +0 -19
- data/lib/concurrent/actor/utills.rb +0 -7
@@ -2,8 +2,9 @@ module Concurrent
|
|
2
2
|
module Actor
|
3
3
|
module Behaviour
|
4
4
|
|
5
|
-
# Links the actor to other actors and sends events to them,
|
5
|
+
# Links the actor to other actors and sends actor's events to them,
|
6
6
|
# like: `:terminated`, `:paused`, errors, etc
|
7
|
+
# TODO example
|
7
8
|
class Linking < Abstract
|
8
9
|
def initialize(core, subsequent)
|
9
10
|
super core, subsequent
|
@@ -16,6 +17,8 @@ module Concurrent
|
|
16
17
|
link envelope.sender
|
17
18
|
when :unlink
|
18
19
|
unlink envelope.sender
|
20
|
+
when :linked?
|
21
|
+
@linked.include? envelope.sender
|
19
22
|
else
|
20
23
|
pass envelope
|
21
24
|
end
|
@@ -5,8 +5,8 @@ module Concurrent
|
|
5
5
|
# Allows to pause actors on errors.
|
6
6
|
# When paused all arriving messages are collected and processed after the actor
|
7
7
|
# is resumed or reset. Resume will simply continue with next message.
|
8
|
-
# Reset also reinitialized context.
|
9
|
-
#
|
8
|
+
# Reset also reinitialized context.
|
9
|
+
# TODO example
|
10
10
|
class Pausing < Abstract
|
11
11
|
def initialize(core, subsequent)
|
12
12
|
super core, subsequent
|
@@ -2,8 +2,9 @@ module Concurrent
|
|
2
2
|
module Actor
|
3
3
|
module Behaviour
|
4
4
|
|
5
|
-
# Sets
|
6
|
-
# for each actor. Each supervisor is automatically linked.
|
5
|
+
# Sets and holds the supervisor of the actor if any. There is at most one supervisor
|
6
|
+
# for each actor. Each supervisor is automatically linked. Messages:
|
7
|
+
# `:pause!, :resume!, :reset!, :restart!` are accepted only from supervisor.
|
7
8
|
class Supervised < Abstract
|
8
9
|
attr_reader :supervisor
|
9
10
|
|
@@ -4,7 +4,7 @@ module Concurrent
|
|
4
4
|
# Terminates all children when the actor terminates.
|
5
5
|
class TerminatesChildren < Abstract
|
6
6
|
def on_event(event)
|
7
|
-
children.
|
7
|
+
children.map { |ch| ch.ask :terminate! }.each(&:wait) if event == :terminated
|
8
8
|
super event
|
9
9
|
end
|
10
10
|
end
|
@@ -115,7 +115,8 @@ module Concurrent
|
|
115
115
|
undef_method :spawn
|
116
116
|
end
|
117
117
|
|
118
|
-
# Basic Context of an Actor.
|
118
|
+
# Basic Context of an Actor. It does not support supervision and pausing.
|
119
|
+
# It simply terminates on error.
|
119
120
|
#
|
120
121
|
# - linking
|
121
122
|
# - terminates on error
|
@@ -37,7 +37,7 @@ module Concurrent
|
|
37
37
|
# @option opts [true, false] link, atomically link the actor to its parent
|
38
38
|
# @option opts [true, false] supervise, atomically supervise the actor by its parent
|
39
39
|
# @option opts [Array<Array(Behavior::Abstract, Array<Object>)>] behaviour_definition, array of pairs
|
40
|
-
# where each pair is behaviour class and its args, see {Behaviour.
|
40
|
+
# where each pair is behaviour class and its args, see {Behaviour.basic_behaviour_definition}
|
41
41
|
# @option opts [IVar, nil] initialized, if present it'll be set or failed after {Context} initialization
|
42
42
|
# @option opts [Proc, nil] logger a proc accepting (level, progname, message = nil, &block) params,
|
43
43
|
# can be used to hook actor instance to any logging system
|
@@ -46,10 +46,14 @@ module Concurrent
|
|
46
46
|
synchronize do
|
47
47
|
@mailbox = Array.new
|
48
48
|
@serialized_execution = SerializedExecution.new
|
49
|
-
@executor = Type! opts.fetch(:executor, Concurrent.configuration.global_task_pool), Executor
|
50
49
|
@children = Set.new
|
51
|
-
|
50
|
+
|
51
|
+
@context_class = Child! opts.fetch(:class), AbstractContext
|
52
52
|
allocate_context
|
53
|
+
|
54
|
+
@executor = Type! opts.fetch(:executor, Concurrent.configuration.global_task_pool), Executor
|
55
|
+
raise ArgumentError, 'ImmediateExecutor is not supported' if @executor.is_a? ImmediateExecutor
|
56
|
+
|
53
57
|
@reference = (Child! opts[:reference_class] || @context.default_reference_class, Reference).new self
|
54
58
|
@name = (Type! opts.fetch(:name), String, Symbol).to_s
|
55
59
|
|
@@ -82,7 +86,7 @@ module Concurrent
|
|
82
86
|
handle_envelope Envelope.new(message, nil, parent, reference)
|
83
87
|
end
|
84
88
|
|
85
|
-
initialized.set
|
89
|
+
initialized.set reference if initialized
|
86
90
|
rescue => ex
|
87
91
|
log ERROR, ex
|
88
92
|
@first_behaviour.terminate!
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Concurrent
|
2
|
+
module Actor
|
3
|
+
module Utils
|
4
|
+
# Allows quick creation of actors with behaviour defined by blocks.
|
5
|
+
# @example ping
|
6
|
+
# AdHoc.spawn :forward, an_actor do |where|
|
7
|
+
# # this block has to return proc defining #on_message behaviour
|
8
|
+
# -> message { where.tell message }
|
9
|
+
# end
|
10
|
+
class AdHoc < Context
|
11
|
+
def initialize(*args, &initializer)
|
12
|
+
@on_message = Type! initializer.call(*args), Proc
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_message(message)
|
16
|
+
instance_exec message, &@on_message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Concurrent
|
2
|
+
module Actor
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
# Distributes messages between subscribed actors. Each actor'll get only one message then
|
6
|
+
# it's unsubscribed. The actor needs to resubscribe when it's ready to receive next message.
|
7
|
+
# It will buffer the messages if there is no worker registered.
|
8
|
+
# @see Pool
|
9
|
+
class Balancer < RestartingContext
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@receivers = []
|
13
|
+
@buffer = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_message(message)
|
17
|
+
case message
|
18
|
+
when :subscribe
|
19
|
+
@receivers << envelope.sender
|
20
|
+
distribute
|
21
|
+
true
|
22
|
+
when :unsubscribe
|
23
|
+
@receivers.delete envelope.sender
|
24
|
+
true
|
25
|
+
when :subscribed?
|
26
|
+
@receivers.include? envelope.sender
|
27
|
+
else
|
28
|
+
@buffer << envelope
|
29
|
+
distribute
|
30
|
+
Behaviour::MESSAGE_PROCESSED
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def distribute
|
35
|
+
while !@receivers.empty? && !@buffer.empty?
|
36
|
+
redirect @receivers.shift, @buffer.shift
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -4,8 +4,20 @@ module Concurrent
|
|
4
4
|
module Actor
|
5
5
|
module Utils
|
6
6
|
|
7
|
-
#
|
8
|
-
|
7
|
+
# Allows to build pub/sub easily.
|
8
|
+
# @example news
|
9
|
+
# news_channel = Concurrent::Actor::Utils::Broadcast.spawn :news
|
10
|
+
#
|
11
|
+
# 2.times do |i|
|
12
|
+
# Concurrent::Actor::Utils::AdHoc.spawn "listener-#{i}" do
|
13
|
+
# news_channel << :subscribe
|
14
|
+
# -> message { puts message }
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# news_channel << 'Ruby rocks!'
|
19
|
+
# # prints: 'Ruby rocks!' twice
|
20
|
+
class Broadcast < RestartingContext
|
9
21
|
|
10
22
|
def initialize
|
11
23
|
@receivers = Set.new
|
@@ -14,11 +26,14 @@ module Concurrent
|
|
14
26
|
def on_message(message)
|
15
27
|
case message
|
16
28
|
when :subscribe
|
17
|
-
|
18
|
-
|
29
|
+
if envelope.sender.is_a? Reference
|
30
|
+
@receivers.add envelope.sender
|
31
|
+
true
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
19
35
|
when :unsubscribe
|
20
|
-
|
21
|
-
true
|
36
|
+
!!@receivers.delete(envelope.sender)
|
22
37
|
when :subscribed?
|
23
38
|
@receivers.include? envelope.sender
|
24
39
|
else
|
@@ -31,6 +46,7 @@ module Concurrent
|
|
31
46
|
@receivers
|
32
47
|
end
|
33
48
|
end
|
49
|
+
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'concurrent/actor/utils/balancer'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
module Actor
|
5
|
+
module Utils
|
6
|
+
|
7
|
+
# Allows to create a pool of workers and distribute work between them
|
8
|
+
# @param [Integer] size number of workers
|
9
|
+
# @yield [balancer, index] a block spawning an worker instance. called +size+ times.
|
10
|
+
# The worker should be descendant of AbstractWorker and supervised, see example.
|
11
|
+
# @yieldparam [Balancer] balancer to pass to the worker
|
12
|
+
# @yieldparam [Integer] index of the worker, usually used in its name
|
13
|
+
# @yieldreturn [Reference] the reference of newly created worker
|
14
|
+
# @example
|
15
|
+
# class Worker < Concurrent::Actor::Utils::AbstractWorker
|
16
|
+
# def work(message)
|
17
|
+
# p message * 5
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# pool = Concurrent::Actor::Utils::Pool.spawn! 'pool', 5 do |balancer, index|
|
22
|
+
# Worker.spawn name: "worker-#{index}", supervise: true, args: [balancer]
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# pool << 'asd' << 2
|
26
|
+
# # prints:
|
27
|
+
# # "asdasdasdasdasd"
|
28
|
+
# # 10
|
29
|
+
class Pool < RestartingContext
|
30
|
+
def initialize(size, &worker_initializer)
|
31
|
+
@balancer = Balancer.spawn name: :balancer, supervise: true
|
32
|
+
@workers = Array.new(size, &worker_initializer.curry[@balancer])
|
33
|
+
@workers.each { |w| Type! w, Reference }
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_message(message)
|
37
|
+
redirect @balancer
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class AbstractWorker < RestartingContext
|
42
|
+
def initialize(balancer)
|
43
|
+
@balancer = balancer
|
44
|
+
@balancer << :subscribe
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_message(message)
|
48
|
+
work message
|
49
|
+
ensure
|
50
|
+
@balancer << :subscribe
|
51
|
+
end
|
52
|
+
|
53
|
+
def work(message)
|
54
|
+
raise NotImplementedError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/concurrent/agent.rb
CHANGED
@@ -8,28 +8,7 @@ require 'concurrent/logging'
|
|
8
8
|
|
9
9
|
module Concurrent
|
10
10
|
|
11
|
-
#
|
12
|
-
# of the agent can be requested at any time (`#deref`). Each agent has a work queue and operates on
|
13
|
-
# the global thread pool. Consumers can `#post` code blocks to the agent. The code block (function)
|
14
|
-
# will receive the current value of the agent as its sole parameter. The return value of the block
|
15
|
-
# will become the new value of the agent. Agents support two error handling modes: fail and continue.
|
16
|
-
# A good example of an agent is a shared incrementing counter, such as the score in a video game.
|
17
|
-
#
|
18
|
-
# @example Basic usage
|
19
|
-
# score = Concurrent::Agent.new(10)
|
20
|
-
# score.value #=> 10
|
21
|
-
#
|
22
|
-
# score << proc{|current| current + 100 }
|
23
|
-
# sleep(0.1)
|
24
|
-
# score.value #=> 110
|
25
|
-
#
|
26
|
-
# score << proc{|current| current * 2 }
|
27
|
-
# sleep(0.1)
|
28
|
-
# score.value #=> 220
|
29
|
-
#
|
30
|
-
# score << proc{|current| current - 50 }
|
31
|
-
# sleep(0.1)
|
32
|
-
# score.value #=> 170
|
11
|
+
# {include:file:doc/agent.md}
|
33
12
|
#
|
34
13
|
# @!attribute [r] timeout
|
35
14
|
# @return [Fixnum] the maximum number of seconds before an update is cancelled
|
data/lib/concurrent/async.rb
CHANGED
@@ -8,85 +8,7 @@ require 'concurrent/executor/serialized_execution'
|
|
8
8
|
|
9
9
|
module Concurrent
|
10
10
|
|
11
|
-
#
|
12
|
-
# class/object or object.
|
13
|
-
#
|
14
|
-
# Scenario:
|
15
|
-
# As a stateful, plain old Ruby class/object
|
16
|
-
# I want safe, asynchronous behavior
|
17
|
-
# So my long-running methods don't block the main thread
|
18
|
-
#
|
19
|
-
# Stateful, mutable objects must be managed carefully when used asynchronously.
|
20
|
-
# But Ruby is an object-oriented language so designing with objects and classes
|
21
|
-
# plays to Ruby's strengths and is often more natural to many Ruby programmers.
|
22
|
-
# The `Async` module is a way to mix simple yet powerful asynchronous capabilities
|
23
|
-
# into any plain old Ruby object or class. These capabilities provide a reasonable
|
24
|
-
# level of thread safe guarantees when used correctly.
|
25
|
-
#
|
26
|
-
# When this module is mixed into a class or object it provides to new methods:
|
27
|
-
# `async` and `await`. These methods are thread safe with respect to the enclosing
|
28
|
-
# object. The former method allows methods to be called asynchronously by posting
|
29
|
-
# to the global thread pool. The latter allows a method to be called synchronously
|
30
|
-
# on the current thread but does so safely with respect to any pending asynchronous
|
31
|
-
# method calls. Both methods return an `Obligation` which can be inspected for
|
32
|
-
# the result of the method call. Calling a method with `async` will return a
|
33
|
-
# `:pending` `Obligation` whereas `await` will return a `:complete` `Obligation`.
|
34
|
-
#
|
35
|
-
# Very loosely based on the `async` and `await` keywords in C#.
|
36
|
-
#
|
37
|
-
# @example Defining an asynchronous class
|
38
|
-
# class Echo
|
39
|
-
# include Concurrent::Async
|
40
|
-
#
|
41
|
-
# def initialize
|
42
|
-
# init_mutex # initialize the internal synchronization objects
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# def echo(msg)
|
46
|
-
# sleep(rand)
|
47
|
-
# print "#{msg}\n"
|
48
|
-
# nil
|
49
|
-
# end
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# horn = Echo.new
|
53
|
-
# horn.echo('zero') # synchronous, not thread-safe
|
54
|
-
#
|
55
|
-
# horn.async.echo('one') # asynchronous, non-blocking, thread-safe
|
56
|
-
# horn.await.echo('two') # synchronous, blocking, thread-safe
|
57
|
-
#
|
58
|
-
# @example Monkey-patching an existing object
|
59
|
-
# numbers = 1_000_000.times.collect{ rand }
|
60
|
-
# numbers.extend(Concurrent::Async)
|
61
|
-
# numbers.init_mutex # initialize the internal synchronization objects
|
62
|
-
#
|
63
|
-
# future = numbers.async.max
|
64
|
-
# future.state #=> :pending
|
65
|
-
#
|
66
|
-
# sleep(2)
|
67
|
-
#
|
68
|
-
# future.state #=> :fulfilled
|
69
|
-
# future.value #=> 0.999999138918843
|
70
|
-
#
|
71
|
-
# @note This module depends on several internal synchronization objects that
|
72
|
-
# must be initialized prior to calling any of the async/await/executor methods.
|
73
|
-
# The best practice is to call `init_mutex` from within the constructor
|
74
|
-
# of the including class. A less ideal but acceptable practice is for the
|
75
|
-
# thread creating the asynchronous object to explicitly call the `init_mutex`
|
76
|
-
# method prior to calling any of the async/await/executor methods. If
|
77
|
-
# `init_mutex` is *not* called explicitly the async/await/executor methods
|
78
|
-
# will raize a `Concurrent::InitializationError`. This is the only way
|
79
|
-
# thread-safe initialization can be guaranteed.
|
80
|
-
#
|
81
|
-
# @note Thread safe guarantees can only be made when asynchronous method calls
|
82
|
-
# are not mixed with synchronous method calls. Use only synchronous calls
|
83
|
-
# when the object is used exclusively on a single thread. Use only
|
84
|
-
# `async` and `await` when the object is shared between threads. Once you
|
85
|
-
# call a method using `async`, you should no longer call any methods
|
86
|
-
# directly on the object. Use `async` and `await` exclusively from then on.
|
87
|
-
# With careful programming it is possible to switch back and forth but it's
|
88
|
-
# also very easy to create race conditions and break your application.
|
89
|
-
# Basically, it's "async all the way down."
|
11
|
+
# {include:file:doc/async.md}
|
90
12
|
#
|
91
13
|
# @since 0.6.0
|
92
14
|
#
|
data/lib/concurrent/atomic.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
#####################################################################
|
2
|
+
# Attempt to check for the deprecated ruby-atomic gem and warn the
|
3
|
+
# user that they should use the new implementation instead.
|
4
|
+
|
5
|
+
if defined?(Atomic)
|
6
|
+
warn <<-RUBY
|
7
|
+
[ATOMIC] Detected an `Atomic` class, which may indicate a dependency
|
8
|
+
on the ruby-atomic gem. That gem has been deprecated and merged into
|
9
|
+
the concurrent-ruby gem. Please use the Concurrent::Atomic class for
|
10
|
+
atomic references and not the Atomic class.
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
#####################################################################
|
14
|
+
|
1
15
|
require 'concurrent/atomic_reference/concurrent_update_error'
|
2
16
|
require 'concurrent/atomic_reference/mutex_atomic'
|
3
17
|
|
@@ -11,7 +25,7 @@ begin
|
|
11
25
|
|
12
26
|
require "concurrent/atomic_reference/#{ruby_engine}"
|
13
27
|
rescue LoadError
|
14
|
-
warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
|
28
|
+
#warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
|
15
29
|
end
|
16
30
|
|
17
31
|
if defined? Concurrent::JavaAtomic
|
@@ -57,41 +71,21 @@ if defined? Concurrent::JavaAtomic
|
|
57
71
|
class Concurrent::Atomic < Concurrent::JavaAtomic
|
58
72
|
end
|
59
73
|
|
60
|
-
elsif defined? Concurrent::CAtomic
|
61
|
-
|
62
|
-
# @!macro [attach] concurrent_update_error
|
63
|
-
#
|
64
|
-
# This exception may be thrown by methods that have detected concurrent
|
65
|
-
# modification of an object when such modification is not permissible.
|
66
|
-
class Concurrent::Atomic < Concurrent::CAtomic
|
67
|
-
end
|
68
|
-
|
69
74
|
elsif defined? Concurrent::RbxAtomic
|
70
75
|
|
71
76
|
# @!macro atomic_reference
|
72
77
|
class Concurrent::Atomic < Concurrent::RbxAtomic
|
73
78
|
end
|
74
79
|
|
75
|
-
|
80
|
+
elsif Concurrent.allow_c_native_class?('CAtomic')
|
76
81
|
|
77
82
|
# @!macro atomic_reference
|
78
|
-
class Concurrent::Atomic < Concurrent::
|
83
|
+
class Concurrent::Atomic < Concurrent::CAtomic
|
79
84
|
end
|
80
|
-
end
|
81
85
|
|
82
|
-
|
83
|
-
class Atomic < Concurrent::Atomic
|
84
|
-
|
85
|
-
# @!macro concurrent_update_error
|
86
|
-
ConcurrentUpdateError = Class.new(Concurrent::ConcurrentUpdateError)
|
86
|
+
else
|
87
87
|
|
88
|
-
# @!macro
|
89
|
-
|
90
|
-
# Creates a new Atomic reference with null initial value.
|
91
|
-
#
|
92
|
-
# @param [Object] value the initial value
|
93
|
-
def initialize(value)
|
94
|
-
warn "[DEPRECATED] Please use Concurrent::Atomic instead."
|
95
|
-
super
|
88
|
+
# @!macro atomic_reference
|
89
|
+
class Concurrent::Atomic < Concurrent::MutexAtomic
|
96
90
|
end
|
97
91
|
end
|