Module: Celluloid

Included in:
Group, Pool, Supervisor, Worker::Manager
Defined in:
lib/celluloid.rb,
lib/celluloid/fsm.rb,
lib/celluloid/pool.rb,
lib/celluloid/task.rb,
lib/celluloid/uuid.rb,
lib/celluloid/actor.rb,
lib/celluloid/calls.rb,
lib/celluloid/group.rb,
lib/celluloid/links.rb,
lib/celluloid/events.rb,
lib/celluloid/future.rb,
lib/celluloid/logger.rb,
lib/celluloid/timers.rb,
lib/celluloid/worker.rb,
lib/celluloid/mailbox.rb,
lib/celluloid/signals.rb,
lib/celluloid/version.rb,
lib/celluloid/registry.rb,
lib/celluloid/receivers.rb,
lib/celluloid/responses.rb,
lib/celluloid/supervisor.rb,
lib/celluloid/actor_proxy.rb,
lib/celluloid/cpu_counter.rb,
lib/celluloid/internal_pool.rb,
lib/celluloid/thread_handle.rb

Defined Under Namespace

Modules: CPUCounter, ClassMethods, FSM, InternalPool, Logger, Registry, UUID, Worker Classes: AbortError, Actor, ActorProxy, AsyncCall, Call, DeadActorError, DeadTaskError, ErrorResponse, ExitEvent, Future, Group, Links, Mailbox, MailboxError, MailboxShutdown, NamingRequest, NotActorError, Pool, Receiver, Receivers, Response, Signals, SuccessResponse, Supervisor, SyncCall, SystemEvent, Task, TerminationRequest, ThreadHandle, Timer, Timers

Constant Summary collapse

SHUTDOWN_TIMEOUT =

How long actors have to terminate

120
VERSION =
'0.10.2'

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object

Process async calls via method_missing



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/celluloid.rb', line 306

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(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
      # async calls should find other ways to deal with actors dying
      # during an async call (i.e. linking/supervisors)
    end

    return
  end

  super
end

Class Attribute Details

.loggerObject

Thread-safe logger class



10
11
12
# File 'lib/celluloid.rb', line 10

def logger
  @logger
end

Class Method Details

.actor?Boolean

Are we currently inside of an actor?

Returns:

  • (Boolean)


17
18
19
# File 'lib/celluloid.rb', line 17

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

.coresObject Also known as: cpus, ncpus

Obtain the number of CPUs in the system



57
58
59
# File 'lib/celluloid.rb', line 57

def cores
  CPUCounter.cores
end

.current_actorObject

Obtain the currently running actor (if one exists)



27
28
29
# File 'lib/celluloid.rb', line 27

def current_actor
  Actor.current
end

.exception_handler(&block) ⇒ Object

Define an exception handler for actor crashes



64
65
66
# File 'lib/celluloid.rb', line 64

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

.exclusive?Boolean

Is current actor running in exclusive mode?

Returns:

  • (Boolean)


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

def exclusive?
  actor? and Thread.current[:actor].exclusive?
end

.included(klass) ⇒ Object



12
13
14
# File 'lib/celluloid.rb', line 12

def included(klass)
  klass.send :extend, ClassMethods
end

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

Receive an asynchronous message



32
33
34
35
36
37
38
39
# File 'lib/celluloid.rb', line 32

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

.shutdownObject

Shut down all running actors FIXME: This should probably attempt a graceful shutdown of the supervision tree before iterating through all actors and telling them to terminate.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/celluloid.rb', line 71

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 = Actor.all.each do |actor|
      begin
        actor.future(:terminate)
      rescue DeadActorError, MailboxError
      end
    end

    terminators.each do |terminator|
      begin
        terminator.value
      rescue DeadActorError, MailboxError
      end
    end

    Logger.info "Shutdown completed cleanly"
  end
end

.sleep(interval) ⇒ Object

Sleep letting the actor continue processing messages



42
43
44
45
46
47
48
49
# File 'lib/celluloid.rb', line 42

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

.uuidObject

Generate a Universally Unique Identifier



52
53
54
# File 'lib/celluloid.rb', line 52

def uuid
  UUID.generate
end

.versionObject



3
# File 'lib/celluloid/version.rb', line 3

def self.version; VERSION; end

Instance Method Details

#abort(cause) ⇒ Object

Raise an exception in caller context, but stay running

Raises:



179
180
181
# File 'lib/celluloid.rb', line 179

def abort(cause)
  raise AbortError.new(cause)
end

#after(interval, &block) ⇒ Object

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



277
278
279
# File 'lib/celluloid.rb', line 277

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

#alive?Boolean

Is this actor alive?

Returns:

  • (Boolean)


174
175
176
# File 'lib/celluloid.rb', line 174

def alive?
  Thread.current[:actor].alive?
end

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

Handle async calls within an actor itself



296
297
298
# File 'lib/celluloid.rb', line 296

def async(meth, *args, &block)
  Actor.async Thread.current[:actor].mailbox, meth, *args, &block
end

#current_actorObject

Obtain the current_actor



209
210
211
# File 'lib/celluloid.rb', line 209

def current_actor
  Actor.current
end

#defer(&block) ⇒ Object

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



289
290
291
292
293
# File 'lib/celluloid.rb', line 289

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



282
283
284
# File 'lib/celluloid.rb', line 282

def every(interval, &block)
  Thread.current[: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.



272
273
274
# File 'lib/celluloid.rb', line 272

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

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

Handle calls to future within an actor itself



301
302
303
# File 'lib/celluloid.rb', line 301

def future(meth, *args, &block)
  Actor.future Thread.current[:actor].mailbox, meth, *args, &block
end

#inspectObject



188
189
190
191
192
193
194
195
196
# File 'lib/celluloid.rb', line 188

def inspect
  str = "#<Celluloid::Actor(#{self.class}:0x#{object_id.to_s(16)})"
  ivars = instance_variables.map do |ivar|
    "#{ivar}=#{instance_variable_get(ivar).inspect}"
  end

  str << " " << ivars.join(' ') unless ivars.empty?
  str << ">"
end

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



236
237
238
239
# File 'lib/celluloid.rb', line 236

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

#linked_to?(actor) ⇒ Boolean

Is this actor linked to another?

Returns:

  • (Boolean)


256
257
258
# File 'lib/celluloid.rb', line 256

def linked_to?(actor)
  Thread.current[:actor].links.include? actor
end

Obtain the Celluloid::Links for this actor



231
232
233
# File 'lib/celluloid.rb', line 231

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

#nameObject

Obtain the name of the current actor



214
215
216
# File 'lib/celluloid.rb', line 214

def name
  Actor.name
end


247
248
249
# File 'lib/celluloid.rb', line 247

def notify_link(actor)
  links << actor
end


251
252
253
# File 'lib/celluloid.rb', line 251

def notify_unlink(actor)
  links.delete actor
end

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

Receive an asynchronous message via the actor protocol



261
262
263
# File 'lib/celluloid.rb', line 261

def receive(timeout = nil, &block)
  Celluloid.receive(timeout, &block)
end

#signal(name, value = nil) ⇒ Object

Send a signal with the given name to all waiting methods



199
200
201
# File 'lib/celluloid.rb', line 199

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

#sleep(interval) ⇒ Object

Sleep while letting the actor continue to receive messages



266
267
268
# File 'lib/celluloid.rb', line 266

def sleep(interval)
  Celluloid.sleep(interval)
end

#tasksObject

Obtain the running tasks for this actor



219
220
221
# File 'lib/celluloid.rb', line 219

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

#terminateObject

Terminate this actor



184
185
186
# File 'lib/celluloid.rb', line 184

def terminate
  Thread.current[:actor].terminate
end

Remove links to another actor



242
243
244
245
# File 'lib/celluloid.rb', line 242

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

#wait(name) ⇒ Object

Wait for the given signal



204
205
206
# File 'lib/celluloid.rb', line 204

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

#wrapped_objectObject

Obtain the Ruby object the actor is wrapping. This should ONLY be used for a limited set of use cases like runtime metaprogramming. Interacting directly with the wrapped object foregoes any kind of thread safety that Celluloid would ordinarily provide you, and the object is guaranteed to be shared with at least the actor thread. Tread carefully.



228
# File 'lib/celluloid.rb', line 228

def wrapped_object; self; end