concurrent-ruby 0.8.0.pre2-java → 0.9.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +114 -3
- data/README.md +111 -55
- data/lib/concurrent.rb +90 -14
- data/lib/concurrent/async.rb +143 -51
- data/lib/concurrent/atom.rb +131 -0
- data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
- data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
- data/lib/concurrent/atomic/atomic_reference.rb +49 -0
- data/lib/concurrent/atomic/condition.rb +23 -12
- data/lib/concurrent/atomic/count_down_latch.rb +23 -21
- data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
- data/lib/concurrent/atomic/event.rb +33 -42
- data/lib/concurrent/atomic/read_write_lock.rb +252 -0
- data/lib/concurrent/atomic/semaphore.rb +64 -89
- data/lib/concurrent/atomic/thread_local_var.rb +130 -58
- data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
- data/lib/concurrent/atomic_reference/jruby.rb +6 -3
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
- data/lib/concurrent/atomic_reference/rbx.rb +4 -1
- data/lib/concurrent/atomic_reference/ruby.rb +6 -3
- data/lib/concurrent/atomics.rb +74 -4
- data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
- data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
- data/lib/concurrent/collection/priority_queue.rb +300 -245
- data/lib/concurrent/concern/deprecation.rb +34 -0
- data/lib/concurrent/concern/dereferenceable.rb +88 -0
- data/lib/concurrent/concern/logging.rb +27 -0
- data/lib/concurrent/concern/obligation.rb +228 -0
- data/lib/concurrent/concern/observable.rb +85 -0
- data/lib/concurrent/configuration.rb +234 -109
- data/lib/concurrent/dataflow.rb +2 -3
- data/lib/concurrent/delay.rb +141 -50
- data/lib/concurrent/edge.rb +30 -0
- data/lib/concurrent/errors.rb +19 -7
- data/lib/concurrent/exchanger.rb +25 -1
- data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
- data/lib/concurrent/executor/executor.rb +46 -299
- data/lib/concurrent/executor/executor_service.rb +521 -0
- data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
- data/lib/concurrent/executor/immediate_executor.rb +9 -9
- data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
- data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
- data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
- data/lib/concurrent/executor/safe_task_executor.rb +5 -4
- data/lib/concurrent/executor/serialized_execution.rb +22 -18
- data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
- data/lib/concurrent/executor/single_thread_executor.rb +32 -21
- data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
- data/lib/concurrent/executor/timer_set.rb +96 -84
- data/lib/concurrent/executors.rb +1 -1
- data/lib/concurrent/future.rb +71 -38
- data/lib/concurrent/immutable_struct.rb +89 -0
- data/lib/concurrent/ivar.rb +152 -60
- data/lib/concurrent/lazy_register.rb +40 -20
- data/lib/concurrent/maybe.rb +226 -0
- data/lib/concurrent/mutable_struct.rb +227 -0
- data/lib/concurrent/mvar.rb +44 -43
- data/lib/concurrent/promise.rb +229 -136
- data/lib/concurrent/scheduled_task.rb +341 -43
- data/lib/concurrent/settable_struct.rb +127 -0
- data/lib/concurrent/synchronization.rb +17 -0
- data/lib/concurrent/synchronization/abstract_object.rb +163 -0
- data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
- data/lib/concurrent/synchronization/condition.rb +53 -0
- data/lib/concurrent/synchronization/java_object.rb +34 -0
- data/lib/concurrent/synchronization/lock.rb +32 -0
- data/lib/concurrent/synchronization/monitor_object.rb +26 -0
- data/lib/concurrent/synchronization/mutex_object.rb +43 -0
- data/lib/concurrent/synchronization/object.rb +78 -0
- data/lib/concurrent/synchronization/rbx_object.rb +75 -0
- data/lib/concurrent/timer_task.rb +92 -103
- data/lib/concurrent/tvar.rb +42 -38
- data/lib/concurrent/utilities.rb +3 -1
- data/lib/concurrent/utility/at_exit.rb +97 -0
- data/lib/concurrent/utility/engine.rb +44 -0
- data/lib/concurrent/utility/monotonic_time.rb +59 -0
- data/lib/concurrent/utility/native_extension_loader.rb +56 -0
- data/lib/concurrent/utility/processor_counter.rb +156 -0
- data/lib/concurrent/utility/timeout.rb +18 -14
- data/lib/concurrent/utility/timer.rb +11 -6
- data/lib/concurrent/version.rb +2 -1
- data/lib/concurrent_ruby.rb +1 -0
- data/lib/concurrent_ruby_ext.jar +0 -0
- metadata +46 -66
- data/lib/concurrent/actor.rb +0 -103
- data/lib/concurrent/actor/behaviour.rb +0 -70
- data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
- data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
- data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
- data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
- data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
- data/lib/concurrent/actor/behaviour/linking.rb +0 -45
- data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
- data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
- data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
- data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
- data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
- data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
- data/lib/concurrent/actor/behaviour/termination.rb +0 -54
- data/lib/concurrent/actor/context.rb +0 -154
- data/lib/concurrent/actor/core.rb +0 -217
- data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
- data/lib/concurrent/actor/envelope.rb +0 -41
- data/lib/concurrent/actor/errors.rb +0 -27
- data/lib/concurrent/actor/internal_delegations.rb +0 -49
- data/lib/concurrent/actor/public_delegations.rb +0 -40
- data/lib/concurrent/actor/reference.rb +0 -81
- data/lib/concurrent/actor/root.rb +0 -37
- data/lib/concurrent/actor/type_check.rb +0 -48
- data/lib/concurrent/actor/utils.rb +0 -10
- data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
- data/lib/concurrent/actor/utils/balancer.rb +0 -42
- data/lib/concurrent/actor/utils/broadcast.rb +0 -52
- data/lib/concurrent/actor/utils/pool.rb +0 -59
- data/lib/concurrent/actress.rb +0 -3
- data/lib/concurrent/agent.rb +0 -209
- data/lib/concurrent/atomic.rb +0 -92
- data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
- data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
- data/lib/concurrent/atomic/synchronization.rb +0 -51
- data/lib/concurrent/channel/buffered_channel.rb +0 -85
- data/lib/concurrent/channel/channel.rb +0 -41
- data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
- data/lib/concurrent/channel/waitable_list.rb +0 -40
- data/lib/concurrent/channels.rb +0 -5
- data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
- data/lib/concurrent/collection/ring_buffer.rb +0 -59
- data/lib/concurrent/collections.rb +0 -3
- data/lib/concurrent/dereferenceable.rb +0 -108
- data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
- data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
- data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
- data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
- data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
- data/lib/concurrent/logging.rb +0 -20
- data/lib/concurrent/obligation.rb +0 -171
- data/lib/concurrent/observable.rb +0 -73
- data/lib/concurrent/options_parser.rb +0 -48
- data/lib/concurrent/utility/processor_count.rb +0 -152
- data/lib/extension_helper.rb +0 -37
@@ -1,27 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
Error = Class.new(StandardError)
|
4
|
-
|
5
|
-
class ActorTerminated < Error
|
6
|
-
include TypeCheck
|
7
|
-
|
8
|
-
attr_reader :reference
|
9
|
-
|
10
|
-
def initialize(reference)
|
11
|
-
@reference = Type! reference, Reference
|
12
|
-
super reference.path
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class UnknownMessage < Error
|
17
|
-
include TypeCheck
|
18
|
-
|
19
|
-
attr_reader :envelope
|
20
|
-
|
21
|
-
def initialize(envelope)
|
22
|
-
@envelope = Type! envelope, Envelope
|
23
|
-
super envelope.message.inspect
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
module InternalDelegations
|
4
|
-
include PublicDelegations
|
5
|
-
|
6
|
-
# @see Core#children
|
7
|
-
def children
|
8
|
-
core.children
|
9
|
-
end
|
10
|
-
|
11
|
-
# @see Core#terminate!
|
12
|
-
def terminate!
|
13
|
-
behaviour!(Behaviour::Termination).terminate!
|
14
|
-
end
|
15
|
-
|
16
|
-
# delegates to core.log
|
17
|
-
# @see Logging#log
|
18
|
-
def log(level, message = nil, &block)
|
19
|
-
core.log(level, message, &block)
|
20
|
-
end
|
21
|
-
|
22
|
-
# @see AbstractContext#dead_letter_routing
|
23
|
-
def dead_letter_routing
|
24
|
-
context.dead_letter_routing
|
25
|
-
end
|
26
|
-
|
27
|
-
def redirect(reference, envelope = self.envelope)
|
28
|
-
reference.message(envelope.message, envelope.ivar)
|
29
|
-
Behaviour::MESSAGE_PROCESSED
|
30
|
-
end
|
31
|
-
|
32
|
-
# @return [AbstractContext]
|
33
|
-
def context
|
34
|
-
core.context
|
35
|
-
end
|
36
|
-
|
37
|
-
# see Core#behaviour
|
38
|
-
def behaviour(behaviour_class)
|
39
|
-
core.behaviour(behaviour_class)
|
40
|
-
end
|
41
|
-
|
42
|
-
# see Core#behaviour!
|
43
|
-
def behaviour!(behaviour_class)
|
44
|
-
core.behaviour!(behaviour_class)
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
|
4
|
-
# Provides publicly expose-able methods from {Core}.
|
5
|
-
module PublicDelegations
|
6
|
-
# @see Core#name
|
7
|
-
def name
|
8
|
-
core.name
|
9
|
-
end
|
10
|
-
|
11
|
-
# @see Core#path
|
12
|
-
def path
|
13
|
-
core.path
|
14
|
-
end
|
15
|
-
|
16
|
-
# @see Core#parent
|
17
|
-
def parent
|
18
|
-
core.parent
|
19
|
-
end
|
20
|
-
|
21
|
-
# @see Core#reference
|
22
|
-
def reference
|
23
|
-
core.reference
|
24
|
-
end
|
25
|
-
|
26
|
-
# @see Core#executor
|
27
|
-
def executor
|
28
|
-
core.executor
|
29
|
-
end
|
30
|
-
|
31
|
-
# @see Core#context_class
|
32
|
-
def context_class
|
33
|
-
core.context_class
|
34
|
-
end
|
35
|
-
|
36
|
-
alias_method :ref, :reference
|
37
|
-
alias_method :actor_class, :context_class
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
|
4
|
-
# Reference is public interface of Actor instances. It is used for sending messages and can
|
5
|
-
# be freely passed around the program. It also provides some basic information about the actor,
|
6
|
-
# see {PublicDelegations}.
|
7
|
-
class Reference
|
8
|
-
include TypeCheck
|
9
|
-
include PublicDelegations
|
10
|
-
|
11
|
-
attr_reader :core
|
12
|
-
private :core
|
13
|
-
|
14
|
-
# @!visibility private
|
15
|
-
def initialize(core)
|
16
|
-
@core = Type! core, Core
|
17
|
-
end
|
18
|
-
|
19
|
-
# tells message to the actor, returns immediately
|
20
|
-
# @param [Object] message
|
21
|
-
# @return [Reference] self
|
22
|
-
def tell(message)
|
23
|
-
message message, nil
|
24
|
-
end
|
25
|
-
|
26
|
-
alias_method :<<, :tell
|
27
|
-
|
28
|
-
# @note it's a good practice to use tell whenever possible. Ask should be used only for
|
29
|
-
# testing and when it returns very shortly. It can lead to deadlock if all threads in
|
30
|
-
# global_task_pool will block on while asking. It's fine to use it form outside of actors and
|
31
|
-
# global_task_pool.
|
32
|
-
#
|
33
|
-
# sends message to the actor and asks for the result of its processing, returns immediately
|
34
|
-
# @param [Object] message
|
35
|
-
# @param [Ivar] ivar to be fulfilled be message's processing result
|
36
|
-
# @return [IVar] supplied ivar
|
37
|
-
def ask(message, ivar = IVar.new)
|
38
|
-
message message, ivar
|
39
|
-
end
|
40
|
-
|
41
|
-
# @note it's a good practice to use tell whenever possible. Ask should be used only for
|
42
|
-
# testing and when it returns very shortly. It can lead to deadlock if all threads in
|
43
|
-
# global_task_pool will block on while asking. It's fine to use it form outside of actors and
|
44
|
-
# global_task_pool.
|
45
|
-
#
|
46
|
-
# sends message to the actor and asks for the result of its processing, blocks
|
47
|
-
# @param [Object] message
|
48
|
-
# @param [Ivar] ivar to be fulfilled be message's processing result
|
49
|
-
# @return [Object] message's processing result
|
50
|
-
# @raise [Exception] ivar.reason if ivar is #rejected?
|
51
|
-
def ask!(message, ivar = IVar.new)
|
52
|
-
ask(message, ivar).value!
|
53
|
-
end
|
54
|
-
|
55
|
-
# behaves as {#tell} when no ivar and as {#ask} when ivar
|
56
|
-
def message(message, ivar = nil)
|
57
|
-
core.on_envelope Envelope.new(message, ivar, Actor.current || Thread.current, self)
|
58
|
-
return ivar || self
|
59
|
-
end
|
60
|
-
|
61
|
-
# @see AbstractContext#dead_letter_routing
|
62
|
-
def dead_letter_routing
|
63
|
-
core.dead_letter_routing
|
64
|
-
end
|
65
|
-
|
66
|
-
def to_s
|
67
|
-
"#<#{self.class} #{path} (#{actor_class})>"
|
68
|
-
end
|
69
|
-
|
70
|
-
alias_method :inspect, :to_s
|
71
|
-
|
72
|
-
def ==(other)
|
73
|
-
Type? other, self.class and other.send(:core) == core
|
74
|
-
end
|
75
|
-
|
76
|
-
# to avoid confusion with Kernel.spawn
|
77
|
-
undef_method :spawn
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
# implements the root actor
|
4
|
-
class Root < AbstractContext
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
# noinspection RubyArgCount
|
8
|
-
@dead_letter_router = Core.new(parent: reference,
|
9
|
-
class: DefaultDeadLetterHandler,
|
10
|
-
supervise: true,
|
11
|
-
name: :default_dead_letter_handler).reference
|
12
|
-
end
|
13
|
-
|
14
|
-
# to allow spawning of new actors, spawn needs to be called inside the parent Actor
|
15
|
-
def on_message(message)
|
16
|
-
case
|
17
|
-
when message.is_a?(Array) && message.first == :spawn
|
18
|
-
Actor.spawn message[1], &message[2]
|
19
|
-
when message == :dead_letter_routing
|
20
|
-
@dead_letter_router
|
21
|
-
else
|
22
|
-
# ignore
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def dead_letter_routing
|
27
|
-
@dead_letter_router
|
28
|
-
end
|
29
|
-
|
30
|
-
def behaviour_definition
|
31
|
-
[*Behaviour.base,
|
32
|
-
[Behaviour::Supervising, [:reset!, :one_for_one]],
|
33
|
-
*Behaviour.user_messages(:just_log)]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
module Actor
|
3
|
-
|
4
|
-
# taken from Algebrick
|
5
|
-
# supplies type-checking helpers whenever included
|
6
|
-
module TypeCheck
|
7
|
-
|
8
|
-
def Type?(value, *types)
|
9
|
-
types.any? { |t| value.is_a? t }
|
10
|
-
end
|
11
|
-
|
12
|
-
def Type!(value, *types)
|
13
|
-
Type?(value, *types) or
|
14
|
-
TypeCheck.error(value, 'is not', types)
|
15
|
-
value
|
16
|
-
end
|
17
|
-
|
18
|
-
def Match?(value, *types)
|
19
|
-
types.any? { |t| t === value }
|
20
|
-
end
|
21
|
-
|
22
|
-
def Match!(value, *types)
|
23
|
-
Match?(value, *types) or
|
24
|
-
TypeCheck.error(value, 'is not matching', types)
|
25
|
-
value
|
26
|
-
end
|
27
|
-
|
28
|
-
def Child?(value, *types)
|
29
|
-
Type?(value, Class) &&
|
30
|
-
types.any? { |t| value <= t }
|
31
|
-
end
|
32
|
-
|
33
|
-
def Child!(value, *types)
|
34
|
-
Child?(value, *types) or
|
35
|
-
TypeCheck.error(value, 'is not child', types)
|
36
|
-
value
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def self.error(value, message, types)
|
42
|
-
raise TypeError,
|
43
|
-
"Value (#{value.class}) '#{value}' #{message} any of: #{types.join('; ')}."
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
@@ -1,21 +0,0 @@
|
|
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
|
@@ -1,42 +0,0 @@
|
|
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
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
module Actor
|
5
|
-
module Utils
|
6
|
-
|
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
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
@receivers = Set.new
|
24
|
-
end
|
25
|
-
|
26
|
-
def on_message(message)
|
27
|
-
case message
|
28
|
-
when :subscribe
|
29
|
-
if envelope.sender.is_a? Reference
|
30
|
-
@receivers.add envelope.sender
|
31
|
-
true
|
32
|
-
else
|
33
|
-
false
|
34
|
-
end
|
35
|
-
when :unsubscribe
|
36
|
-
!!@receivers.delete(envelope.sender)
|
37
|
-
when :subscribed?
|
38
|
-
@receivers.include? envelope.sender
|
39
|
-
else
|
40
|
-
filtered_receivers.each { |r| r << message }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# override to define different behaviour, filtering etc
|
45
|
-
def filtered_receivers
|
46
|
-
@receivers
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,59 +0,0 @@
|
|
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
|