lib/celluloid.rb in celluloid-0.15.2 vs lib/celluloid.rb in celluloid-0.16.0.pre

- old
+ new

@@ -1,50 +1,67 @@ require 'logger' require 'thread' require 'timeout' require 'set' -if defined?(JRUBY_VERSION) && JRUBY_VERSION == "1.7.3" - raise "Celluloid is broken on JRuby 1.7.3. Please upgrade to 1.7.4+" -end - module Celluloid - VERSION = '0.15.2' - Error = Class.new StandardError + # Expose all instance methods as singleton methods + extend self - extend self # expose all instance methods as singleton methods + VERSION = '0.16.0.pre' + # Linking times out after 5 seconds + LINKING_TIMEOUT = 5 + # Warning message added to Celluloid objects accessed outside their actors BARE_OBJECT_WARNING_MESSAGE = "WARNING: BARE CELLULOID OBJECT " class << self - attr_accessor :internal_pool # Internal thread pool + attr_writer :actor_system # Default Actor System attr_accessor :logger # Thread-safe logger class attr_accessor :task_class # Default task type to use attr_accessor :shutdown_timeout # How long actors have to terminate + def actor_system + if Thread.current.celluloid? + Thread.current[:celluloid_actor_system] or raise Error, "actor system not running" + else + Thread.current[:celluloid_actor_system] || @actor_system or raise Error, "Celluloid is not yet started; use Celluloid.boot" + end + end + def included(klass) klass.send :extend, ClassMethods klass.send :include, InstanceMethods klass.send :extend, Properties klass.property :mailbox_class, :default => Celluloid::Mailbox - klass.property :proxy_class, :default => Celluloid::ActorProxy + klass.property :proxy_class, :default => Celluloid::CellProxy klass.property :task_class, :default => Celluloid.task_class klass.property :mailbox_size + klass.property :exclusive_actor, :default => false + klass.property :exclusive_methods, :multi => true klass.property :execute_block_on_receiver, :default => [:after, :every, :receive], :multi => true klass.property :finalizer - klass.property :exit_handler + klass.property :exit_handler_name klass.send(:define_singleton_method, :trap_exit) do |*args| - exit_handler(*args) + exit_handler_name(*args) end + + klass.send(:define_singleton_method, :exclusive) do |*args| + if args.any? + exclusive_methods(*exclusive_methods, *args) + else + exclusive_actor true + end + end end # Are we currently inside of an actor? def actor? !!Thread.current[:celluloid_actor] @@ -67,11 +84,11 @@ alias_method :cpus, :cores alias_method :ncpus, :cores # Perform a stack dump of all actors to the given output object def stack_dump(output = STDERR) - Celluloid::StackDump.new.dump(output) + actor_system.stack_dump.print(output) end alias_method :dump, :stack_dump # Detect if a particular call is recursing through multiple actors def detect_recursion @@ -104,22 +121,19 @@ init start end def init - self.internal_pool = InternalPool.new + @actor_system = ActorSystem.new end - # Launch default services - # FIXME: We should set up the supervision hierarchy here def start - Celluloid::Notifications::Fanout.supervise_as :notifications_fanout - Celluloid::IncidentReporter.supervise_as :default_incident_reporter, STDERR + actor_system.start end def running? - internal_pool + actor_system && actor_system.running? end def register_shutdown return if @shutdown_registered # Terminate all actors at exit @@ -137,45 +151,11 @@ @shutdown_registered = true end # Shut down all running actors def shutdown - actors = Actor.all - - Timeout.timeout(shutdown_timeout) do - internal_pool.shutdown - - Logger.debug "Terminating #{actors.size} #{(actors.size > 1) ? 'actors' : 'actor'}..." 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 - actors.each do |actor| - begin - actor.terminate! - rescue DeadActorError - end - end - - actors.each do |actor| - begin - Actor.join(actor) - rescue DeadActorError - end - end - end - rescue Timeout::Error - Logger.error("Couldn't cleanly terminate all actors in #{shutdown_timeout} seconds!") - actors.each do |actor| - begin - Actor.kill(actor) - rescue DeadActorError, MailboxDead - end - end - ensure - internal_pool.kill + actor_system.shutdown end def version VERSION end @@ -183,21 +163,21 @@ # Class methods added to classes which include Celluloid module ClassMethods # Create a new actor def new(*args, &block) - proxy = Actor.new(allocate, actor_options).proxy + proxy = Cell.new(allocate, behavior_options, actor_options).proxy proxy._send_(:initialize, *args, &block) proxy end alias_method :spawn, :new # Create a new actor and link to the current one def new_link(*args, &block) raise NotActorError, "can't link outside actor context" unless Celluloid.actor? - proxy = Actor.new(allocate, actor_options).proxy + proxy = Cell.new(allocate, behavior_options, actor_options).proxy Actor.link(proxy) proxy._send_(:initialize, *args, &block) proxy end alias_method :spawn_link, :new_link @@ -231,33 +211,35 @@ # Run an actor in the foreground def run(*args, &block) Actor.join(new(*args, &block)) end - # Mark methods as running exclusively - def exclusive(*methods) - if methods.empty? - @exclusive_methods = :all - elsif !defined?(@exclusive_methods) || @exclusive_methods != :all - @exclusive_methods ||= Set.new - @exclusive_methods.merge methods.map(&:to_sym) - end + def actor_system + Celluloid.actor_system end # Configuration options for Actor#new def actor_options { + :actor_system => actor_system, :mailbox_class => mailbox_class, :mailbox_size => mailbox_size, - :proxy_class => proxy_class, :task_class => task_class, - :exit_handler => exit_handler, - :exclusive_methods => defined?(@exclusive_methods) ? @exclusive_methods : nil, - :receiver_block_executions => execute_block_on_receiver + :exclusive => exclusive_actor, } end + def behavior_options + { + :proxy_class => proxy_class, + :exclusive_methods => exclusive_methods, + :exit_handler_name => exit_handler_name, + :finalizer => finalizer, + :receiver_block_executions => execute_block_on_receiver, + } + end + def ===(other) other.kind_of? self end end @@ -289,23 +271,24 @@ yield current_actor current_actor end # Obtain the name of the current actor - def name - Actor.name + def registered_name + Actor.registered_name end + alias_method :name, :registered_name def inspect return "..." if Celluloid.detect_recursion str = "#<" if leaked? str << Celluloid::BARE_OBJECT_WARNING_MESSAGE else - str << "Celluloid::ActorProxy" + str << "Celluloid::CellProxy" end str << "(#{self.class}:0x#{object_id.to_s(16)})" str << " " unless instance_variables.empty? @@ -333,11 +316,11 @@ raise AbortError.new(cause) end # Terminate this actor def terminate - Thread.current[:celluloid_actor].proxy.terminate! + Thread.current[:celluloid_actor].behavior_proxy.terminate! end # Send a signal with the given name to all waiting methods def signal(name, value = nil) Thread.current[:celluloid_actor].signal name, value @@ -456,19 +439,25 @@ Future.new(&block).value end # Handle async calls within an actor itself def async(meth = nil, *args, &block) - Thread.current[:celluloid_actor].proxy.async meth, *args, &block + Thread.current[:celluloid_actor].behavior_proxy.async meth, *args, &block end # Handle calls to future within an actor itself def future(meth = nil, *args, &block) - Thread.current[:celluloid_actor].proxy.future meth, *args, &block + Thread.current[:celluloid_actor].behavior_proxy.future meth, *args, &block end end +if defined?(JRUBY_VERSION) && JRUBY_VERSION == "1.7.3" + raise "Celluloid is broken on JRuby 1.7.3. Please upgrade to 1.7.4+" +end + +require 'celluloid/exceptions' + require 'celluloid/calls' require 'celluloid/call_chain' require 'celluloid/condition' require 'celluloid/thread' require 'celluloid/core_ext' @@ -480,10 +469,11 @@ require 'celluloid/logger' require 'celluloid/mailbox' require 'celluloid/evented_mailbox' require 'celluloid/method' require 'celluloid/properties' +require 'celluloid/handlers' require 'celluloid/receivers' require 'celluloid/registry' require 'celluloid/responses' require 'celluloid/signals' require 'celluloid/stack_dump' @@ -493,23 +483,28 @@ require 'celluloid/thread_handle' require 'celluloid/uuid' require 'celluloid/proxies/abstract_proxy' require 'celluloid/proxies/sync_proxy' +require 'celluloid/proxies/cell_proxy' require 'celluloid/proxies/actor_proxy' require 'celluloid/proxies/async_proxy' require 'celluloid/proxies/future_proxy' require 'celluloid/proxies/block_proxy' require 'celluloid/actor' +require 'celluloid/cell' require 'celluloid/future' +require 'celluloid/actor_system' require 'celluloid/pool_manager' require 'celluloid/supervision_group' require 'celluloid/supervisor' require 'celluloid/notifications' require 'celluloid/logging' require 'celluloid/legacy' unless defined?(CELLULOID_FUTURE) + +$CELLULOID_MONITORING = false # Configure default systemwide settings Celluloid.task_class = Celluloid::TaskFiber Celluloid.logger = Logger.new(STDERR) Celluloid.shutdown_timeout = 10