lib/celluloid.rb in celluloid-0.10.0 vs lib/celluloid.rb in celluloid-0.11.0

- old
+ new

@@ -71,12 +71,15 @@ def shutdown Timeout.timeout(SHUTDOWN_TIMEOUT) do actors = Actor.all Logger.info "Terminating #{actors.size} actors..." if actors.size > 0 + # Attempt to shut down the supervision tree, if available + Supervisor.root.terminate if Supervisor.root + # Actors cannot self-terminate, you must do it for them - terminators = actors.each do |actor| + terminators = Actor.all.each do |actor| begin actor.future(:terminate) rescue DeadActorError, MailboxError end end @@ -128,10 +131,29 @@ # an actor if it fails, and keep the actor registered under a given name def supervise_as(name, *args, &block) Supervisor.supervise_as(name, self, *args, &block) end + # Create a new pool of workers. Accepts the following options: + # + # * size: how many workers to create. Default is worker per CPU core + # * args: array of arguments to pass when creating a worker + # + def pool(options = {}) + PoolManager.new(self, options) + end + + # Same as pool, but links to the pool manager + def pool_link(options = {}) + PoolManager.new_link(self, options) + end + + # Run an actor in the foreground + def run(*args, &block) + new(*args, &block).join + end + # Trap errors from actors we're linked to when they exit def trap_exit(callback) @exit_handler = callback.to_sym end @@ -172,10 +194,15 @@ Thread.current[:actor].alive? end # Raise an exception in caller context, but stay running def abort(cause) + cause = case cause + when String then RuntimeError.new(cause) + when Exception then cause + else raise TypeError, "Exception object/String expected, but #{cause.class} received" + end raise AbortError.new(cause) end # Terminate this actor def terminate @@ -205,10 +232,15 @@ # Obtain the current_actor def current_actor Actor.current end + # Obtain the name of the current actor + def name + Actor.name + end + # Obtain the running tasks for this actor def tasks Thread.current[:actor].tasks.to_a end @@ -278,21 +310,32 @@ # Perform a blocking or computationally intensive action inside an # asynchronous thread pool, allowing the caller to continue processing other # messages in its mailbox in the meantime def defer(&block) # This implementation relies on the present implementation of - # Celluloid::Future, which uses an Actor to run the block + # Celluloid::Future, which uses a thread from InternalPool to run the block Future.new(&block).value end + # Handle async calls within an actor itself + def async(meth, *args, &block) + Actor.async Thread.current[:actor].mailbox, meth, *args, &block + end + + # Handle calls to future within an actor itself + def future(meth, *args, &block) + Actor.future Thread.current[:actor].mailbox, meth, *args, &block + end + # Process async calls via method_missing def method_missing(meth, *args, &block) # bang methods are async calls if meth.to_s.match(/!$/) unbanged_meth = meth.to_s.sub(/!$/, '') - call = AsyncCall.new(@mailbox, unbanged_meth, args, block) + args.unshift unbanged_meth + call = AsyncCall.new(nil, :__send__, args, block) begin Thread.current[:actor].mailbox << call rescue MailboxError # Silently swallow asynchronous calls to dead actors. There's no way # to reliably generate DeadActorErrors for async calls, so users of @@ -313,22 +356,23 @@ require 'celluloid/core_ext' require 'celluloid/cpu_counter' require 'celluloid/events' require 'celluloid/fiber' require 'celluloid/fsm' +require 'celluloid/internal_pool' require 'celluloid/links' require 'celluloid/logger' require 'celluloid/mailbox' -require 'celluloid/pool' require 'celluloid/receivers' require 'celluloid/registry' require 'celluloid/responses' require 'celluloid/signals' require 'celluloid/task' +require 'celluloid/thread_handle' require 'celluloid/timers' -require 'celluloid/thread_pool' require 'celluloid/uuid' require 'celluloid/actor' require 'celluloid/future' -require 'celluloid/group' +require 'celluloid/pool_manager' +require 'celluloid/supervision_group' require 'celluloid/supervisor'