Module: Celluloid

Extended by:
Celluloid
Included in:
Celluloid, IncidentReporter, Notifications::Fanout, PoolManager, Probe, SupervisionGroup
Defined in:
lib/celluloid.rb,
lib/celluloid/fsm.rb,
lib/celluloid/cell.rb,
lib/celluloid/uuid.rb,
lib/celluloid/actor.rb,
lib/celluloid/tasks.rb,
lib/celluloid/calls.rb,
lib/celluloid/rspec.rb,
lib/celluloid/links.rb,
lib/celluloid/probe.rb,
lib/celluloid/future.rb,
lib/celluloid/logger.rb,
lib/celluloid/thread.rb,
lib/celluloid/method.rb,
lib/celluloid/signals.rb,
lib/celluloid/mailbox.rb,
lib/celluloid/task_set.rb,
lib/celluloid/registry.rb,
lib/celluloid/handlers.rb,
lib/celluloid/condition.rb,
lib/celluloid/responses.rb,
lib/celluloid/receivers.rb,
lib/celluloid/exceptions.rb,
lib/celluloid/call_chain.rb,
lib/celluloid/properties.rb,
lib/celluloid/stack_dump.rb,
lib/celluloid/supervisor.rb,
lib/celluloid/cpu_counter.rb,
lib/celluloid/pool_manager.rb,
lib/celluloid/actor_system.rb,
lib/celluloid/system_events.rb,
lib/celluloid/internal_pool.rb,
lib/celluloid/thread_handle.rb,
lib/celluloid/notifications.rb,
lib/celluloid/evented_mailbox.rb,
lib/celluloid/logging/incident.rb,
lib/celluloid/tasks/task_fiber.rb,
lib/celluloid/logging/log_event.rb,
lib/celluloid/tasks/task_thread.rb,
lib/celluloid/supervision_group.rb,
lib/celluloid/proxies/cell_proxy.rb,
lib/celluloid/proxies/sync_proxy.rb,
lib/celluloid/proxies/block_proxy.rb,
lib/celluloid/proxies/actor_proxy.rb,
lib/celluloid/proxies/async_proxy.rb,
lib/celluloid/logging/ring_buffer.rb,
lib/celluloid/proxies/future_proxy.rb,
lib/celluloid/proxies/abstract_proxy.rb,
lib/celluloid/logging/incident_logger.rb,
lib/celluloid/logging/incident_reporter.rb

Defined Under Namespace

Modules: CPUCounter, ClassMethods, FSM, InstanceMethods, Logger, Notifications, Properties, UUID Classes: AbortError, AbstractProxy, Actor, ActorProxy, ActorSystem, AsyncCall, AsyncProxy, BlockCall, BlockProxy, BlockResponse, Call, CallChain, Cell, CellProxy, Condition, ConditionError, DeadTaskError, ErrorResponse, EventedMailbox, ExitEvent, FiberStackError, Future, FutureProxy, Handler, Handlers, Incident, IncidentLogger, IncidentReporter, InternalPool, LinkingRequest, LinkingResponse, Links, LogEvent, Mailbox, MailboxDead, MailboxShutdown, Method, NamingRequest, NotTaskError, PoolManager, Probe, Receiver, Receivers, Registry, Response, ResumableError, RingBuffer, SignalConditionRequest, Signals, StackDump, SuccessResponse, SupervisionGroup, Supervisor, SyncCall, SyncProxy, SystemEvent, Task, TaskFiber, TaskSet, TaskThread, TerminationRequest, Thread, ThreadHandle

Constant Summary

VERSION =
'0.16.0'
LINKING_TIMEOUT =

Linking times out after 5 seconds

5
BARE_OBJECT_WARNING_MESSAGE =

Warning message added to Celluloid objects accessed outside their actors

"WARNING: BARE CELLULOID OBJECT "
OWNER_IVAR =

reference to owning actor

:@celluloid_owner
TIMER_QUANTUM =

Timer accuracy enforced by the tests (50ms)

0.05
Error =

Base class of all Celluloid errors

Class.new(StandardError)
NotActorError =

Don't do Actor-like things outside Actor scope

Class.new(Celluloid::Error)
DeadActorError =

Trying to do something to a dead actor

Class.new(Celluloid::Error)
TimeoutError =

A timeout occured before the given request could complete

Class.new(Celluloid::Error)

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.actor_systemObject



24
25
26
27
28
29
30
# File 'lib/celluloid.rb', line 24

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

.loggerObject

Returns the value of attribute logger



20
21
22
# File 'lib/celluloid.rb', line 20

def logger
  @logger
end

.shutdown_timeoutObject

Default Actor System Thread-safe logger class Default task type to use How long actors have to terminate



22
23
24
# File 'lib/celluloid.rb', line 22

def shutdown_timeout
  @shutdown_timeout
end

.task_classObject

Returns the value of attribute task_class



21
22
23
# File 'lib/celluloid.rb', line 21

def task_class
  @task_class
end

Class Method Details

.actor?Boolean

Are we currently inside of an actor?

Returns:

  • (Boolean)


66
67
68
# File 'lib/celluloid.rb', line 66

def actor?
  !!Thread.current[:celluloid_actor]
end

.bootObject



120
121
122
123
# File 'lib/celluloid.rb', line 120

def boot
  init
  start
end

.coresObject Also known as: cpus, ncpus

Obtain the number of CPUs in the system



81
82
83
# File 'lib/celluloid.rb', line 81

def cores
 CPUCounter.cores
end

.detect_recursionObject

Detect if a particular call is recursing through multiple actors



94
95
96
97
98
99
100
101
102
103
# File 'lib/celluloid.rb', line 94

def detect_recursion
  actor = Thread.current[:celluloid_actor]
  return unless actor

  task = Thread.current[:celluloid_task]
  return unless task

  chain_id = CallChain.current_id
  actor.tasks.to_a.any? { |t| t != task && t.chain_id == chain_id }
end

.exception_handler(&block) ⇒ Object

Define an exception handler for actor crashes



106
107
108
# File 'lib/celluloid.rb', line 106

def exception_handler(&block)
  Logger.exception_handler(&block)
end

.included(klass) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/celluloid.rb', line 32

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::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_name

  klass.send(:define_singleton_method, :trap_exit) do |*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

.initObject



125
126
127
# File 'lib/celluloid.rb', line 125

def init
  @actor_system = ActorSystem.new
end

.mailboxObject

Retrieve the mailbox for the current thread or lazily initialize it



71
72
73
# File 'lib/celluloid.rb', line 71

def mailbox
  Thread.current[:celluloid_mailbox] ||= Celluloid::Mailbox.new
end

.register_shutdownObject



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/celluloid.rb', line 137

def register_shutdown
  return if @shutdown_registered
  # 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)
      Celluloid.shutdown
      exit exit_status if exit_status
    else
      Celluloid.shutdown
    end
  end
  @shutdown_registered = true
end

.running?Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/celluloid.rb', line 133

def running?
  actor_system && actor_system.running?
end

.shutdownObject

Shut down all running actors



155
156
157
# File 'lib/celluloid.rb', line 155

def shutdown
  actor_system.shutdown
end

.stack_dump(output = STDERR) ⇒ Object Also known as: dump

Perform a stack dump of all actors to the given output object



88
89
90
# File 'lib/celluloid.rb', line 88

def stack_dump(output = STDERR)
  actor_system.stack_dump.print(output)
end

.startObject



129
130
131
# File 'lib/celluloid.rb', line 129

def start
  actor_system.start
end

.suspend(status, waiter) ⇒ Object



110
111
112
113
114
115
116
117
118
# File 'lib/celluloid.rb', line 110

def suspend(status, waiter)
  task = Thread.current[:celluloid_task]
  if task && !Celluloid.exclusive?
    waiter.before_suspend(task) if waiter.respond_to?(:before_suspend)
    Task.suspend(status)
  else
    waiter.wait
  end
end

.uuidObject

Generate a Universally Unique Identifier



76
77
78
# File 'lib/celluloid.rb', line 76

def uuid
  UUID.generate
end

.versionObject



159
160
161
# File 'lib/celluloid.rb', line 159

def version
  VERSION
end

Instance Method Details

#abort(cause) ⇒ Object

Raise an exception in sender context, but stay running

Raises:



310
311
312
313
314
315
316
317
# File 'lib/celluloid.rb', line 310

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

#after(interval, &block) ⇒ Object

Call a block after a given interval, returning a Celluloid::Timer object



424
425
426
# File 'lib/celluloid.rb', line 424

def after(interval, &block)
  Thread.current[:celluloid_actor].after(interval, &block)
end

#async(meth = nil, *args, &block) ⇒ Object

Handle async calls within an actor itself



443
444
445
# File 'lib/celluloid.rb', line 443

def async(meth = nil, *args, &block)
  Thread.current[:celluloid_actor].behavior_proxy.async meth, *args, &block
end

#call_chain_idObject

Obtain the UUID of the current call chain



340
341
342
# File 'lib/celluloid.rb', line 340

def call_chain_id
  CallChain.current_id
end

#current_actorObject

Obtain the current_actor



335
336
337
# File 'lib/celluloid.rb', line 335

def current_actor
  Actor.current
end

#defer(&block) ⇒ Object

Perform a blocking or computationally intensive action inside an asynchronous thread pool, allowing the sender to continue processing other messages in its mailbox in the meantime



436
437
438
439
440
# File 'lib/celluloid.rb', line 436

def defer(&block)
  # This implementation relies on the present implementation of
  # Celluloid::Future, which uses a thread from InternalPool to run the block
  Future.new(&block).value
end

#every(interval, &block) ⇒ Object

Call a block every given interval, returning a Celluloid::Timer object



429
430
431
# File 'lib/celluloid.rb', line 429

def every(interval, &block)
  Thread.current[:celluloid_actor].every(interval, &block)
end

#exclusive(&block) ⇒ Object

Run given block in an exclusive mode: all synchronous calls block the whole actor, not only current message processing.



413
414
415
# File 'lib/celluloid.rb', line 413

def exclusive(&block)
  Thread.current[:celluloid_task].exclusive(&block)
end

#exclusive?Boolean

Are we currently exclusive

Returns:

  • (Boolean)


418
419
420
421
# File 'lib/celluloid.rb', line 418

def exclusive?
  task = Thread.current[:celluloid_task]
  task && task.exclusive?
end

#future(meth = nil, *args, &block) ⇒ Object

Handle calls to future within an actor itself



448
449
450
# File 'lib/celluloid.rb', line 448

def future(meth = nil, *args, &block)
  Thread.current[:celluloid_actor].behavior_proxy.future meth, *args, &block
end

Link this actor to another, allowing it to crash or react to errors



365
366
367
# File 'lib/celluloid.rb', line 365

def link(actor)
  Actor.link(actor)
end

#linked_to?(actor) ⇒ Boolean

Is this actor linked to another?

Returns:

  • (Boolean)


380
381
382
# File 'lib/celluloid.rb', line 380

def linked_to?(actor)
  Actor.linked_to?(actor)
end

Obtain the Celluloid::Links for this actor



350
351
352
# File 'lib/celluloid.rb', line 350

def links
  Thread.current[:celluloid_actor].links
end

#monitor(actor) ⇒ Object

Watch for exit events from another actor



355
356
357
# File 'lib/celluloid.rb', line 355

def monitor(actor)
  Actor.monitor(actor)
end

#monitoring?(actor) ⇒ Boolean

Are we monitoring another actor?

Returns:

  • (Boolean)


375
376
377
# File 'lib/celluloid.rb', line 375

def monitoring?(actor)
  Actor.monitoring?(actor)
end

#receive(timeout = nil, &block) ⇒ Object

Receive an asynchronous message via the actor protocol



385
386
387
388
389
390
391
392
# File 'lib/celluloid.rb', line 385

def receive(timeout = nil, &block)
  actor = Thread.current[:celluloid_actor]
  if actor
    actor.receive(timeout, &block)
  else
    Celluloid.mailbox.receive(timeout, &block)
  end
end

#signal(name, value = nil) ⇒ Object

Send a signal with the given name to all waiting methods



325
326
327
# File 'lib/celluloid.rb', line 325

def signal(name, value = nil)
  Thread.current[:celluloid_actor].signal name, value
end

#sleep(interval) ⇒ Object

Sleep letting the actor continue processing messages



395
396
397
398
399
400
401
402
# File 'lib/celluloid.rb', line 395

def sleep(interval)
  actor = Thread.current[:celluloid_actor]
  if actor
    actor.sleep(interval)
  else
    Kernel.sleep interval
  end
end

#tasksObject

Obtain the running tasks for this actor



345
346
347
# File 'lib/celluloid.rb', line 345

def tasks
  Thread.current[:celluloid_actor].tasks.to_a
end

#terminateObject

Terminate this actor



320
321
322
# File 'lib/celluloid.rb', line 320

def terminate
  Thread.current[:celluloid_actor].behavior_proxy.terminate!
end

#timeout(duration) ⇒ Object

Timeout on task suspension (eg Sync calls to other actors)



405
406
407
408
409
# File 'lib/celluloid.rb', line 405

def timeout(duration)
  Thread.current[:celluloid_actor].timeout(duration) do
    yield
  end
end

Remove links to another actor



370
371
372
# File 'lib/celluloid.rb', line 370

def unlink(actor)
  Actor.unlink(actor)
end

#unmonitor(actor) ⇒ Object

Stop waiting for exit events from another actor



360
361
362
# File 'lib/celluloid.rb', line 360

def unmonitor(actor)
  Actor.unmonitor(actor)
end

#wait(name) ⇒ Object

Wait for the given signal



330
331
332
# File 'lib/celluloid.rb', line 330

def wait(name)
  Thread.current[:celluloid_actor].wait name
end