concurrent-ruby 0.7.0.rc2-java → 0.7.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|