Skip to content

Commit 49906a0

Browse files
committed
Organized files in subdirectories.
1 parent fb742a5 commit 49906a0

File tree

83 files changed

+571
-550
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+571
-550
lines changed

lib/concurrent.rb

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,29 @@
22
require 'concurrent/configuration'
33

44
require 'concurrent/atomic'
5-
require 'concurrent/count_down_latch'
6-
require 'concurrent/condition'
7-
require 'concurrent/copy_on_notify_observer_set'
8-
require 'concurrent/copy_on_write_observer_set'
9-
require 'concurrent/safe_task_executor'
10-
require 'concurrent/ivar'
11-
125
require 'concurrent/actor'
6+
require 'concurrent/channel'
7+
require 'concurrent/executor'
8+
require 'concurrent/utilities'
9+
1310
require 'concurrent/agent'
1411
require 'concurrent/async'
1512
require 'concurrent/dataflow'
1613
require 'concurrent/delay'
1714
require 'concurrent/dereferenceable'
18-
require 'concurrent/event'
1915
require 'concurrent/exchanger'
2016
require 'concurrent/future'
17+
require 'concurrent/ivar'
2118
require 'concurrent/mvar'
2219
require 'concurrent/obligation'
2320
require 'concurrent/observable'
24-
require 'concurrent/postable'
25-
require 'concurrent/processor_count'
2621
require 'concurrent/promise'
2722
require 'concurrent/runnable'
2823
require 'concurrent/scheduled_task'
2924
require 'concurrent/stoppable'
3025
require 'concurrent/supervisor'
31-
require 'concurrent/thread_local_var'
3226
require 'concurrent/timer_task'
3327
require 'concurrent/tvar'
34-
require 'concurrent/utilities'
35-
36-
require 'concurrent/channel/channel'
37-
require 'concurrent/channel/unbuffered_channel'
38-
require 'concurrent/channel/buffered_channel'
39-
require 'concurrent/channel/ring_buffer'
40-
require 'concurrent/channel/blocking_ring_buffer'
41-
42-
require 'concurrent/actor_context'
43-
require 'concurrent/simple_actor_ref'
44-
45-
require 'concurrent/cached_thread_pool'
46-
require 'concurrent/fixed_thread_pool'
47-
require 'concurrent/immediate_executor'
48-
require 'concurrent/per_thread_executor'
49-
require 'concurrent/single_thread_executor'
50-
require 'concurrent/thread_pool_executor'
5128

5229
# Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
5330
# F#, C#, Java, and classic concurrency patterns.

lib/concurrent/actor.rb

Lines changed: 5 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -1,270 +1,5 @@
1-
require 'thread'
2-
require 'observer'
3-
4-
require 'concurrent/event'
5-
require 'concurrent/obligation'
6-
require 'concurrent/postable'
7-
require 'concurrent/runnable'
8-
9-
module Concurrent
10-
11-
# Actor-based concurrency is all the rage in some circles. Originally described in
12-
# 1973, the actor model is a paradigm for creating asynchronous, concurrent objects
13-
# that is becoming increasingly popular. Much has changed since actors were first
14-
# written about four decades ago, which has led to a serious fragmentation within
15-
# the actor community. There is *no* universally accepted, strict definition of
16-
# "actor" and actor implementations differ widely between languages and libraries.
17-
#
18-
# A good definition of "actor" is:
19-
#
20-
# An independent, concurrent, single-purpose, computational entity that communicates exclusively via message passing.
21-
#
22-
# The +Concurrent::Actor+ class in this library is based solely on the
23-
# {http://www.scala-lang.org/api/current/index.html#scala.actors.Actor Actor} trait
24-
# defined in the Scala standard library. It does not implement all the features of
25-
# Scala's +Actor+ but its behavior for what *has* been implemented is nearly identical.
26-
# The excluded features mostly deal with Scala's message semantics, strong typing,
27-
# and other characteristics of Scala that don't really apply to Ruby.
28-
#
29-
# Unlike many of the abstractions in this library, +Actor+ takes an *object-oriented*
30-
# approach to asynchronous concurrency, rather than a *functional programming*
31-
# approach.
32-
#
33-
# Because +Actor+ mixes in the +Concurrent::Runnable+ module subclasses have access to
34-
# the +#on_error+ method and can override it to implement custom error handling. The
35-
# +Actor+ base class does not use +#on_error+ so as to avoid conflit with subclasses
36-
# which override it. Generally speaking, +#on_error+ should not be used. The +Actor+
37-
# base class provides concictent, reliable, and robust error handling already, and
38-
# error handling specifics are tied to the message posting method. Incorrect behavior
39-
# in an +#on_error+ override can lead to inconsistent +Actor+ behavior that may lead
40-
# to confusion and difficult debugging.
41-
#
42-
# The +Actor+ superclass mixes in the Ruby standard library
43-
# {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html Observable}
44-
# module to provide consistent callbacks upon message processing completion. The normal
45-
# +Observable+ methods, including +#add_observer+ behave normally. Once an observer
46-
# is added to an +Actor+ it will be notified of all messages processed *after*
47-
# addition. Notification will *not* occur for any messages that have already been
48-
# processed.
49-
#
50-
# Observers will be notified regardless of whether the message processing is successful
51-
# or not. The +#update+ method of the observer will receive four arguments. The
52-
# appropriate method signature is:
53-
#
54-
# def update(time, message, result, reason)
55-
#
56-
# These four arguments represent:
57-
#
58-
# * The time that message processing was completed
59-
# * An array containing all elements of the original message, in order
60-
# * The result of the call to +#act+ (will be +nil+ if an exception was raised)
61-
# * Any exception raised by +#act+ (or +nil+ if message processing was successful)
62-
#
63-
# @example Actor Ping Pong
64-
# class Ping < Concurrent::Actor
65-
#
66-
# def initialize(count, pong)
67-
# super()
68-
# @pong = pong
69-
# @remaining = count
70-
# end
71-
#
72-
# def act(msg)
73-
#
74-
# if msg == :pong
75-
# print "Ping: pong\n" if @remaining % 1000 == 0
76-
# @pong.post(:ping)
77-
#
78-
# if @remaining > 0
79-
# @pong << :ping
80-
# @remaining -= 1
81-
# else
82-
# print "Ping :stop\n"
83-
# @pong << :stop
84-
# self.stop
85-
# end
86-
# end
87-
# end
88-
# end
89-
#
90-
# class Pong < Concurrent::Actor
91-
#
92-
# attr_writer :ping
93-
#
94-
# def initialize
95-
# super()
96-
# @count = 0
97-
# end
98-
#
99-
# def act(msg)
100-
#
101-
# if msg == :ping
102-
# print "Pong: ping\n" if @count % 1000 == 0
103-
# @ping << :pong
104-
# @count += 1
105-
#
106-
# elsif msg == :stop
107-
# print "Pong :stop\n"
108-
# self.stop
109-
# end
110-
# end
111-
# end
112-
#
113-
# pong = Pong.new
114-
# ping = Ping.new(10000, pong)
115-
# pong.ping = ping
116-
#
117-
# t1 = ping.run!
118-
# t2 = pong.run!
119-
#
120-
# ping << :pong
121-
#
122-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
123-
#
124-
# @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
125-
class Actor
126-
include ::Observable
127-
include Postable
128-
include Runnable
129-
130-
private
131-
132-
# @!visibility private
133-
class Poolbox # :nodoc:
134-
include Postable
135-
136-
def initialize(queue)
137-
@queue = queue
138-
end
139-
end
140-
141-
public
142-
143-
# Create a pool of actors that share a common mailbox.
144-
#
145-
# Every +Actor+ instance operates on its own thread. When one thread isn't enough capacity
146-
# to manage all the messages being sent to an +Actor+ a *pool* can be used instead. A pool
147-
# is a collection of +Actor+ instances, all of the same type, that shate a message queue.
148-
# Messages from other threads are all sent to a single queue against which all +Actor+s
149-
# load balance.
150-
#
151-
# @param [Integer] count the number of actors in the pool
152-
# @param [Array] args zero or more arguments to pass to each actor in the pool
153-
#
154-
# @return [Array] two-element array with the shared mailbox as the first element
155-
# and an array of actors as the second element
156-
#
157-
# @raise ArgumentError if +count+ is zero or less
158-
#
159-
# @example
160-
# class EchoActor < Concurrent::Actor
161-
# def act(*message)
162-
# puts "#{message} handled by #{self}"
163-
# end
164-
# end
165-
#
166-
# mailbox, pool = EchoActor.pool(5)
167-
# pool.each{|echo| echo.run! }
168-
#
169-
# 10.times{|i| mailbox.post(i) }
170-
# #=> [0] handled by #<EchoActor:0x007fc8014fb8b8>
171-
# #=> [1] handled by #<EchoActor:0x007fc8014fb890>
172-
# #=> [2] handled by #<EchoActor:0x007fc8014fb868>
173-
# #=> [3] handled by #<EchoActor:0x007fc8014fb890>
174-
# #=> [4] handled by #<EchoActor:0x007fc8014fb840>
175-
# #=> [5] handled by #<EchoActor:0x007fc8014fb8b8>
176-
# #=> [6] handled by #<EchoActor:0x007fc8014fb8b8>
177-
# #=> [7] handled by #<EchoActor:0x007fc8014fb818>
178-
# #=> [8] handled by #<EchoActor:0x007fc8014fb890>
179-
#
180-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
181-
def self.pool(count, *args, &block)
182-
warn '[DEPRECATED] `Actor` is deprecated and will be replaced with `ActorContext`.'
183-
raise ArgumentError.new('count must be greater than zero') unless count > 0
184-
mailbox = Queue.new
185-
actors = count.times.collect do
186-
if block_given?
187-
actor = self.new(*args, &block.dup)
188-
else
189-
actor = self.new(*args)
190-
end
191-
actor.instance_variable_set(:@queue, mailbox)
192-
actor
193-
end
194-
return Poolbox.new(mailbox), actors
195-
end
196-
197-
protected
198-
199-
# Actors are defined by subclassing the +Concurrent::Actor+ class and overriding the
200-
# #act method. The #act method can have any signature/arity but +def act(*args)+
201-
# is the most flexible and least error-prone signature. The #act method is called in
202-
# response to a message being post to the +Actor+ instance (see *Behavior* below).
203-
#
204-
# @param [Array] message one or more arguments representing the message sent to the
205-
# actor via one of the Concurrent::Postable methods
206-
#
207-
# @return [Object] the result obtained when the message is successfully processed
208-
#
209-
# @raise NotImplementedError unless overridden in the +Actor+ subclass
210-
#
211-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
212-
#
213-
# @!visibility public
214-
def act(*message)
215-
warn '[DEPRECATED] `Actor` is deprecated and will be replaced with `ActorContext`.'
216-
raise NotImplementedError.new("#{self.class} does not implement #act")
217-
end
218-
219-
# @!visibility private
220-
#
221-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
222-
def on_run # :nodoc:
223-
warn '[DEPRECATED] `Actor` is deprecated and will be replaced with `ActorContext`.'
224-
queue.clear
225-
end
226-
227-
# @!visibility private
228-
#
229-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
230-
def on_stop # :nodoc:
231-
queue.clear
232-
queue.push(:stop)
233-
end
234-
235-
# @!visibility private
236-
#
237-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
238-
def on_task # :nodoc:
239-
package = queue.pop
240-
return if package == :stop
241-
result = ex = nil
242-
notifier = package.notifier
243-
begin
244-
if notifier.nil? || (notifier.is_a?(Event) && ! notifier.set?)
245-
result = act(*package.message)
246-
end
247-
rescue => ex
248-
on_error(Time.now, package.message, ex)
249-
ensure
250-
if notifier.is_a?(Event) && ! notifier.set?
251-
package.handler.push(result || ex)
252-
package.notifier.set
253-
elsif package.handler.is_a?(IVar)
254-
package.handler.complete(! result.nil?, result, ex)
255-
elsif package.handler.respond_to?(:post) && ex.nil?
256-
package.handler.post(result)
257-
end
258-
259-
changed
260-
notify_observers(Time.now, package.message, result, ex)
261-
end
262-
end
263-
264-
# @!visibility private
265-
#
266-
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
267-
def on_error(time, msg, ex) # :nodoc:
268-
end
269-
end
270-
end
1+
require 'concurrent/actor/actor'
2+
require 'concurrent/actor/actor_context'
3+
require 'concurrent/actor/actor_ref'
4+
require 'concurrent/actor/postable'
5+
require 'concurrent/actor/simple_actor_ref'

0 commit comments

Comments
 (0)