lib/celluloid.rb in celluloid-0.12.4 vs lib/celluloid.rb in celluloid-0.13.0.pre
- old
+ new
@@ -1,50 +1,49 @@
require 'logger'
require 'thread'
require 'timeout'
require 'set'
-require 'facter'
module Celluloid
extend self # expose all instance methods as singleton methods
# How long actors have to terminate
- SHUTDOWN_TIMEOUT = 120
+ SHUTDOWN_TIMEOUT = 10
# Warning message added to Celluloid objects accessed outside their actors
BARE_OBJECT_WARNING_MESSAGE = "WARNING: BARE CELLULOID OBJECT "
class << self
- attr_accessor :logger # Thread-safe logger class
- attr_accessor :task_class # Default task type to use
+ attr_accessor :internal_pool # Internal thread pool
+ attr_accessor :logger # Thread-safe logger class
+ attr_accessor :task_class # Default task type to use
def included(klass)
klass.send :extend, ClassMethods
klass.send :include, InstanceMethods
end
# Are we currently inside of an actor?
def actor?
- !!Thread.current[:actor]
+ !!Thread.current[:celluloid_actor]
end
# Generate a Universally Unique Identifier
def uuid
UUID.generate
end
# Obtain the number of CPUs in the system
def cores
- core_count = Facter.fact(:processorcount).value
- Integer(core_count)
+ CPUCounter.cores
end
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::StackDumper.dump(output)
+ Celluloid::StackDump.new.dump(output)
end
alias_method :dump, :stack_dump
# Define an exception handler for actor crashes
def exception_handler(&block)
@@ -75,26 +74,15 @@
end
end
Logger.debug "Shutdown completed cleanly"
end
+ rescue Timeout::Error => ex
+ Logger.error("Couldn't cleanly terminate all actors in #{SHUTDOWN_TIMEOUT} seconds!")
end
end
- # Terminate all actors at exit
- at_exit do
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION >= "1.9"
- # workaround for MRI bug losing exit status in at_exit block
- # http://bugs.ruby-lang.org/issues/5218
- exit_status = $!.status if $!.is_a?(SystemExit)
- shutdown
- exit exit_status if exit_status
- else
- shutdown
- end
- end
-
# 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
@@ -155,26 +143,44 @@
superclass.exit_handler
end
end
alias_method :trap_exit, :exit_handler
- # Configure a custom mailbox factory
- def use_mailbox(klass = nil, &block)
- if block
- @mailbox_factory = block
- else
- mailbox_class(klass)
+ # Define a callback to run when the actor is finalized.
+ def finalizer(callback = nil)
+ if callback
+ @finalizer = callback.to_sym
+ elsif defined?(@finalizer)
+ @finalizer
+ elsif superclass.respond_to? :finalizer
+ superclass.finalizer
end
end
# Define the mailbox class for this class
- def mailbox_class(klass)
- @mailbox_factory = proc { klass.new }
+ def mailbox_class(klass = nil)
+ if klass
+ @mailbox_class = klass
+ elsif defined?(@mailbox_class)
+ @mailbox_class
+ elsif superclass.respond_to? :mailbox_class
+ superclass.mailbox_class
+ else
+ Celluloid::Mailbox
+ end
end
- def proxy_class(klass)
- @proxy_factory = proc { klass }
+ def proxy_class(klass = nil)
+ if klass
+ @proxy_class = klass
+ elsif defined?(@proxy_class)
+ @proxy_class
+ elsif superclass.respond_to? :proxy_class
+ superclass.proxy_class
+ else
+ Celluloid::ActorProxy
+ end
end
# Define the default task type for this class
def task_class(klass = nil)
if klass
@@ -196,39 +202,18 @@
@exclusive_methods ||= Set.new
@exclusive_methods.merge methods.map(&:to_sym)
end
end
- # Create a mailbox for this actor
- def mailbox_factory
- if defined?(@mailbox_factory)
- @mailbox_factory.call
- elsif superclass.respond_to? :mailbox_factory
- superclass.mailbox_factory
- else
- Mailbox.new
- end
- end
-
- def proxy_factory
- if defined?(@proxy_factory)
- @proxy_factory.call
- elsif superclass.respond_to?(:proxy_factory)
- superclass.proxy_factory
- else
- nil
- end
- end
-
# Configuration options for Actor#new
def actor_options
{
- :mailbox => mailbox_factory,
- :proxy_class => proxy_factory,
+ :mailbox => mailbox_class.new,
+ :proxy_class => proxy_class,
+ :task_class => task_class,
:exit_handler => exit_handler,
- :exclusive_methods => @exclusive_methods,
- :task_class => task_class
+ :exclusive_methods => @exclusive_methods
}
end
def ===(other)
other.kind_of? self
@@ -254,20 +239,20 @@
def bare_object; self; end
alias_method :wrapped_object, :bare_object
# Are we being invoked in a different thread from our owner?
def leaked?
- @celluloid_owner != Thread.current[:actor]
+ @celluloid_owner != Thread.current[:celluloid_actor]
end
def inspect
str = "#<"
if leaked?
str << Celluloid::BARE_OBJECT_WARNING_MESSAGE
else
- str << "Celluloid::Actor"
+ str << "Celluloid::ActorProxy"
end
str << "(#{self.class}:0x#{object_id.to_s(16)})"
str << " " unless instance_variables.empty?
@@ -276,33 +261,10 @@
str << "#{ivar}=#{instance_variable_get(ivar).inspect} "
end
str.sub!(/\s$/, '>')
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(/!$/, '')
- args.unshift unbanged_meth
-
- call = AsyncCall.new(:__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
- # async calls should find other ways to deal with actors dying
- # during an async call (i.e. linking/supervisors)
- end
-
- return
- end
-
- super
- end
end
#
# The following methods are available on both the Celluloid singleton and
# directly inside of all classes that include Celluloid
@@ -318,41 +280,46 @@
raise AbortError.new(cause)
end
# Terminate this actor
def terminate
- Thread.current[:actor].terminate
+ Thread.current[:celluloid_actor].terminate
end
# Send a signal with the given name to all waiting methods
def signal(name, value = nil)
- Thread.current[:actor].signal name, value
+ Thread.current[:celluloid_actor].signal name, value
end
# Wait for the given signal
def wait(name)
- Thread.current[:actor].wait name
+ Thread.current[:celluloid_actor].wait name
end
# Obtain the current_actor
def current_actor
Actor.current
end
+ # Obtain the UUID of the current call chain
+ def call_chain_id
+ Thread.current[:celluloid_chain_id]
+ 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
+ Thread.current[:celluloid_actor].tasks.to_a
end
# Obtain the Celluloid::Links for this actor
def links
- Thread.current[:actor].links
+ Thread.current[:celluloid_actor].links
end
# Watch for exit events from another actor
def monitor(actor)
Actor.monitor(actor)
@@ -383,48 +350,48 @@
Actor.linked_to?(actor)
end
# Receive an asynchronous message via the actor protocol
def receive(timeout = nil, &block)
- actor = Thread.current[:actor]
+ actor = Thread.current[:celluloid_actor]
if actor
actor.receive(timeout, &block)
else
Thread.mailbox.receive(timeout, &block)
end
end
# Sleep letting the actor continue processing messages
def sleep(interval)
- actor = Thread.current[:actor]
+ actor = Thread.current[:celluloid_actor]
if actor
actor.sleep(interval)
else
Kernel.sleep interval
end
end
# Run given block in an exclusive mode: all synchronous calls block the whole
# actor, not only current message processing.
def exclusive(&block)
- Thread.current[:actor].exclusive(&block)
+ Thread.current[:celluloid_actor].exclusive(&block)
end
# Are we currently exclusive
def exclusive?
- actor = Thread.current[:actor]
+ actor = Thread.current[:celluloid_actor]
actor && actor.exclusive?
end
# Call a block after a given interval, returning a Celluloid::Timer object
def after(interval, &block)
- Thread.current[:actor].after(interval, &block)
+ Thread.current[:celluloid_actor].after(interval, &block)
end
# Call a block every given interval, returning a Celluloid::Timer object
def every(interval, &block)
- Thread.current[:actor].every(interval, &block)
+ Thread.current[:celluloid_actor].every(interval, &block)
end
# 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
@@ -435,30 +402,32 @@
end
# Handle async calls within an actor itself
def async(meth = nil, *args, &block)
if meth
- Actor.async Thread.current[:actor].mailbox, meth, *args, &block
+ Actor.async Thread.current[:celluloid_actor].mailbox, meth, *args, &block
else
- Thread.current[:actor].proxy.async
+ Thread.current[:celluloid_actor].proxy.async
end
end
# Handle calls to future within an actor itself
def future(meth = nil, *args, &block)
if meth
- Actor.future Thread.current[:actor].mailbox, meth, *args, &block
+ Actor.future Thread.current[:celluloid_actor].mailbox, meth, *args, &block
else
- Thread.current[:actor].proxy.future
+ Thread.current[:celluloid_actor].proxy.future
end
end
end
require 'celluloid/version'
require 'celluloid/calls'
+require 'celluloid/condition'
require 'celluloid/core_ext'
+require 'celluloid/cpu_counter'
require 'celluloid/fiber'
require 'celluloid/fsm'
require 'celluloid/internal_pool'
require 'celluloid/links'
require 'celluloid/logger'
@@ -466,13 +435,13 @@
require 'celluloid/method'
require 'celluloid/receivers'
require 'celluloid/registry'
require 'celluloid/responses'
require 'celluloid/signals'
-require 'celluloid/stack_dumper'
+require 'celluloid/stack_dump'
require 'celluloid/system_events'
-require 'celluloid/task'
+require 'celluloid/tasks'
require 'celluloid/thread_handle'
require 'celluloid/uuid'
require 'celluloid/proxies/abstract_proxy'
require 'celluloid/proxies/actor_proxy'
@@ -485,6 +454,7 @@
require 'celluloid/supervision_group'
require 'celluloid/supervisor'
require 'celluloid/notifications'
require 'celluloid/logging'
+require 'celluloid/legacy' unless defined?(CELLULOID_FUTURE)
require 'celluloid/boot'