celluloid 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -2
  3. data/lib/celluloid/actor.rb +33 -30
  4. data/lib/celluloid/autostart.rb +0 -13
  5. data/lib/celluloid/calls.rb +71 -23
  6. data/lib/celluloid/condition.rb +32 -28
  7. data/lib/celluloid/core_ext.rb +3 -14
  8. data/lib/celluloid/cpu_counter.rb +1 -1
  9. data/lib/celluloid/evented_mailbox.rb +82 -0
  10. data/lib/celluloid/fsm.rb +2 -0
  11. data/lib/celluloid/future.rb +22 -31
  12. data/lib/celluloid/internal_pool.rb +13 -0
  13. data/lib/celluloid/legacy.rb +14 -13
  14. data/lib/celluloid/logging/incident_logger.rb +2 -2
  15. data/lib/celluloid/mailbox.rb +16 -0
  16. data/lib/celluloid/method.rb +7 -7
  17. data/lib/celluloid/notifications.rb +1 -1
  18. data/lib/celluloid/proxies/abstract_proxy.rb +1 -1
  19. data/lib/celluloid/proxies/actor_proxy.rb +23 -27
  20. data/lib/celluloid/proxies/async_proxy.rb +18 -6
  21. data/lib/celluloid/proxies/block_proxy.rb +29 -0
  22. data/lib/celluloid/proxies/future_proxy.rb +17 -3
  23. data/lib/celluloid/proxies/sync_proxy.rb +31 -0
  24. data/lib/celluloid/receivers.rb +1 -1
  25. data/lib/celluloid/responses.rb +13 -1
  26. data/lib/celluloid/stack_dump.rb +8 -5
  27. data/lib/celluloid/supervision_group.rb +10 -10
  28. data/lib/celluloid/system_events.rb +1 -0
  29. data/lib/celluloid/tasks/task_fiber.rb +9 -47
  30. data/lib/celluloid/tasks/task_thread.rb +9 -44
  31. data/lib/celluloid/tasks.rb +63 -2
  32. data/lib/celluloid/thread.rb +38 -0
  33. data/lib/celluloid/thread_handle.rb +5 -3
  34. data/lib/celluloid/version.rb +1 -1
  35. data/lib/celluloid.rb +84 -32
  36. data/spec/support/actor_examples.rb +92 -53
  37. data/spec/support/example_actor_class.rb +7 -1
  38. data/spec/support/mailbox_examples.rb +29 -3
  39. data/spec/support/task_examples.rb +11 -9
  40. metadata +21 -29
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 83a01356fe7e144f11c0ac9db25951850f53c9b4
4
+ data.tar.gz: 243e2915cef408cf97229f8ec0a512bfb2524fb8
5
+ SHA512:
6
+ metadata.gz: 60e75d013b08ff7101ea6280b31bd5976ba097e821880e3d6d9b935580c8515d05d8619bc6a3df7be1d2733366d97b482a3668443e59c3c9e397bc6a14e46c75
7
+ data.tar.gz: 3e9fe0851276289183c6ca52e72bc545dc174831d325d78a9682f63087c4f54ff3b6f454babf4b091641a163235f953e02bbf656cfbdce4e093ec35df831e167
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
  =========
3
3
  [![Gem Version](https://badge.fury.io/rb/celluloid.png)](http://rubygems.org/gems/celluloid)
4
4
  [![Build Status](https://secure.travis-ci.org/celluloid/celluloid.png?branch=master)](http://travis-ci.org/celluloid/celluloid)
5
- [![Dependency Status](https://gemnasium.com/celluloid/celluloid.png)](https://gemnasium.com/celluloid/celluloid)
6
5
  [![Code Climate](https://codeclimate.com/github/celluloid/celluloid.png)](https://codeclimate.com/github/celluloid/celluloid)
7
6
  [![Coverage Status](https://coveralls.io/repos/celluloid/celluloid/badge.png?branch=master)](https://coveralls.io/r/celluloid/celluloid)
8
7
 
@@ -70,7 +69,7 @@ to EventMachine (with a synchronous API instead of callback/deferrable soup)
70
69
  is available through the [Celluloid::IO](https://github.com/celluloid/celluloid-io)
71
70
  library.
72
71
 
73
- Like Celluloid? [Join the Google Group](http://groups.google.com/group/celluloid-ruby)
72
+ Like Celluloid? [Join the mailing list/Google Group](http://groups.google.com/group/celluloid-ruby)
74
73
  or visit us on IRC at #celluloid on freenode
75
74
 
76
75
  ### Is it any good?
@@ -10,7 +10,7 @@ module Celluloid
10
10
  # A timeout occured before the given request could complete
11
11
  class TimeoutError < StandardError; end
12
12
 
13
- # The caller made an error, not the current actor
13
+ # The sender made an error, not the current actor
14
14
  class AbortError < StandardError
15
15
  attr_reader :cause
16
16
 
@@ -58,42 +58,28 @@ module Celluloid
58
58
 
59
59
  # Invoke a method on the given actor via its mailbox
60
60
  def call(mailbox, meth, *args, &block)
61
- call = SyncCall.new(Thread.mailbox, meth, args, block)
62
-
63
- begin
64
- mailbox << call
65
- rescue MailboxError
66
- raise DeadActorError, "attempted to call a dead actor"
67
- end
68
-
69
- Celluloid.suspend(:callwait, call).value
61
+ proxy = SyncProxy.new(mailbox, "UnknownClass")
62
+ proxy.method_missing(meth, *args, &block)
70
63
  end
71
64
 
72
65
  # Invoke a method asynchronously on an actor via its mailbox
73
66
  def async(mailbox, meth, *args, &block)
74
- begin
75
- mailbox << AsyncCall.new(meth, args, block)
76
- rescue MailboxError
77
- # Silently swallow asynchronous calls to dead actors. There's no way
78
- # to reliably generate DeadActorErrors for async calls, so users of
79
- # async calls should find other ways to deal with actors dying
80
- # during an async call (i.e. linking/supervisors)
81
- end
67
+ proxy = AsyncProxy.new(mailbox, "UnknownClass")
68
+ proxy.method_missing(meth, *args, &block)
82
69
  end
83
70
 
84
71
  # Call a method asynchronously and retrieve its value later
85
72
  def future(mailbox, meth, *args, &block)
86
- future = Future.new
87
- future.execute(mailbox, meth, args, block)
88
- future
73
+ proxy = FutureProxy.new(mailbox, "UnknownClass")
74
+ proxy.method_missing(meth, *args, &block)
89
75
  end
90
76
 
91
77
  # Obtain all running actors in the system
92
78
  def all
93
79
  actors = []
94
80
  Thread.list.each do |t|
95
- actor = t[:celluloid_actor]
96
- actors << actor.proxy if actor and actor.respond_to?(:proxy)
81
+ next unless t.celluloid? && t.role == :actor
82
+ actors << t.actor.proxy if t.actor && t.actor.respond_to?(:proxy)
97
83
  end
98
84
  actors
99
85
  end
@@ -142,8 +128,8 @@ module Celluloid
142
128
  end
143
129
 
144
130
  # Wait for an actor to terminate
145
- def join(actor)
146
- actor.thread.join
131
+ def join(actor, timeout = nil)
132
+ actor.thread.join(timeout)
147
133
  actor
148
134
  end
149
135
  end
@@ -154,6 +140,7 @@ module Celluloid
154
140
  @mailbox = options[:mailbox] || Mailbox.new
155
141
  @exit_handler = options[:exit_handler]
156
142
  @exclusives = options[:exclusive_methods]
143
+ @receiver_block_executions = options[:receiver_block_executions]
157
144
  @task_class = options[:task_class] || Celluloid.task_class
158
145
 
159
146
  @tasks = TaskSet.new
@@ -165,9 +152,8 @@ module Celluloid
165
152
  @exclusive = false
166
153
  @name = nil
167
154
 
168
- @thread = ThreadHandle.new do
169
- Thread.current[:celluloid_actor] = self
170
- Thread.current[:celluloid_mailbox] = @mailbox
155
+ @thread = ThreadHandle.new(:actor) do
156
+ setup_thread
171
157
  run
172
158
  end
173
159
 
@@ -175,6 +161,11 @@ module Celluloid
175
161
  @subject.instance_variable_set(OWNER_IVAR, self)
176
162
  end
177
163
 
164
+ def setup_thread
165
+ Thread.current[:celluloid_actor] = self
166
+ Thread.current[:celluloid_mailbox] = @mailbox
167
+ end
168
+
178
169
  # Run the actor loop
179
170
  def run
180
171
  begin
@@ -323,8 +314,20 @@ module Celluloid
323
314
  when SystemEvent
324
315
  handle_system_event message
325
316
  when Call
326
- task(:message_handler, message.method) { message.dispatch(@subject) }
327
- when Response
317
+ task(:call, message.method) {
318
+ if @receiver_block_executions && meth = message.method
319
+ if meth == :__send__
320
+ meth = message.arguments.first
321
+ end
322
+ if @receiver_block_executions.include?(meth.to_sym)
323
+ message.execute_block_on_receiver
324
+ end
325
+ end
326
+ message.dispatch(@subject)
327
+ }
328
+ when BlockCall
329
+ task(:invoke_block) { message.dispatch }
330
+ when BlockResponse, Response
328
331
  message.dispatch
329
332
  else
330
333
  @receivers.handle_message(message)
@@ -1,16 +1,3 @@
1
1
  require 'celluloid'
2
2
 
3
3
  Celluloid.boot
4
-
5
- # Terminate all actors at exit
6
- at_exit do
7
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION >= "1.9"
8
- # workaround for MRI bug losing exit status in at_exit block
9
- # http://bugs.ruby-lang.org/issues/5218
10
- exit_status = $!.status if $!.is_a?(SystemExit)
11
- Celluloid.shutdown
12
- exit exit_status if exit_status
13
- else
14
- Celluloid.shutdown
15
- end
16
- end
@@ -4,19 +4,33 @@ module Celluloid
4
4
  attr_reader :method, :arguments, :block
5
5
 
6
6
  def initialize(method, arguments = [], block = nil)
7
- @method, @arguments, @block = method, arguments, block
7
+ @method, @arguments = method, arguments
8
+ if block
9
+ if Celluloid.exclusive?
10
+ # FIXME: nicer exception
11
+ raise "Cannot execute blocks on sender in exclusive mode"
12
+ end
13
+ @block = BlockProxy.new(self, Celluloid.mailbox, block)
14
+ else
15
+ @block = nil
16
+ end
17
+ end
18
+
19
+ def execute_block_on_receiver
20
+ @block && @block.execution = :receiver
8
21
  end
9
22
 
10
23
  def dispatch(obj)
11
- obj.public_send(@method, *@arguments, &@block)
24
+ _block = @block && @block.to_proc
25
+ obj.public_send(@method, *@arguments, &_block)
12
26
  rescue NoMethodError => ex
13
- # Abort if the caller made a mistake
27
+ # Abort if the sender made a mistake
14
28
  raise AbortError.new(ex) unless obj.respond_to? @method
15
29
 
16
30
  # Otherwise something blew up. Crash this actor
17
31
  raise
18
32
  rescue ArgumentError => ex
19
- # Abort if the caller made a mistake
33
+ # Abort if the sender made a mistake
20
34
  begin
21
35
  arity = obj.method(@method).arity
22
36
  rescue NameError
@@ -34,26 +48,16 @@ module Celluloid
34
48
  # Otherwise something blew up. Crash this actor
35
49
  raise
36
50
  end
37
-
38
- def wait
39
- loop do
40
- message = Thread.mailbox.receive do |msg|
41
- msg.respond_to?(:call) and msg.call == self
42
- end
43
- break message unless message.is_a?(SystemEvent)
44
- Thread.current[:celluloid_actor].handle_system_event(message)
45
- end
46
- end
47
51
  end
48
52
 
49
53
  # Synchronous calls wait for a response
50
54
  class SyncCall < Call
51
- attr_reader :caller, :task, :chain_id
55
+ attr_reader :sender, :task, :chain_id
52
56
 
53
- def initialize(caller, method, arguments = [], block = nil, task = Thread.current[:celluloid_task], chain_id = Thread.current[:celluloid_chain_id])
57
+ def initialize(sender, method, arguments = [], block = nil, task = Thread.current[:celluloid_task], chain_id = Thread.current[:celluloid_chain_id])
54
58
  super(method, arguments, block)
55
59
 
56
- @caller = caller
60
+ @sender = sender
57
61
  @task = task
58
62
  @chain_id = chain_id || Celluloid.uuid
59
63
  end
@@ -64,11 +68,11 @@ module Celluloid
64
68
  respond SuccessResponse.new(self, result)
65
69
  rescue Exception => ex
66
70
  # Exceptions that occur during synchronous calls are reraised in the
67
- # context of the caller
71
+ # context of the sender
68
72
  respond ErrorResponse.new(self, ex)
69
73
 
70
- # Aborting indicates a protocol error on the part of the caller
71
- # It should crash the caller, but the exception isn't reraised
74
+ # Aborting indicates a protocol error on the part of the sender
75
+ # It should crash the sender, but the exception isn't reraised
72
76
  # Otherwise, it's a bug in this actor and should be reraised
73
77
  raise unless ex.is_a?(AbortError)
74
78
  ensure
@@ -81,11 +85,36 @@ module Celluloid
81
85
  end
82
86
 
83
87
  def respond(message)
84
- @caller << message
88
+ @sender << message
85
89
  rescue MailboxError
86
- # It's possible the caller exited or crashed before we could send a
90
+ # It's possible the sender exited or crashed before we could send a
87
91
  # response to them.
88
92
  end
93
+
94
+ def value
95
+ Celluloid.suspend(:callwait, self).value
96
+ end
97
+
98
+ def wait
99
+ loop do
100
+ message = Celluloid.mailbox.receive do |msg|
101
+ msg.respond_to?(:call) and msg.call == self
102
+ end
103
+
104
+ if message.is_a?(SystemEvent)
105
+ Thread.current[:celluloid_actor].handle_system_event(message)
106
+ else
107
+ # FIXME: add check for receiver block execution
108
+ if message.respond_to?(:value)
109
+ # FIXME: disable block execution if on :sender and (exclusive or outside of task)
110
+ # probably now in Call
111
+ break message
112
+ else
113
+ message.dispatch
114
+ end
115
+ end
116
+ end
117
+ end
89
118
  end
90
119
 
91
120
  # Asynchronous calls don't wait for a response
@@ -95,7 +124,7 @@ module Celluloid
95
124
  Thread.current[:celluloid_chain_id] = Celluloid.uuid
96
125
  super(obj)
97
126
  rescue AbortError => ex
98
- # Swallow aborted async calls, as they indicate the caller made a mistake
127
+ # Swallow aborted async calls, as they indicate the sender made a mistake
99
128
  Logger.debug("#{obj.class}: async call `#@method` aborted!\n#{Logger.format_exception(ex.cause)}")
100
129
  ensure
101
130
  Thread.current[:celluloid_chain_id] = nil
@@ -103,4 +132,23 @@ module Celluloid
103
132
 
104
133
  end
105
134
 
135
+ class BlockCall
136
+ def initialize(block_proxy, sender, arguments, task = Thread.current[:celluloid_task])
137
+ @block_proxy = block_proxy
138
+ @sender = sender
139
+ @arguments = arguments
140
+ @task = task
141
+ end
142
+ attr_reader :task
143
+
144
+ def call
145
+ @block_proxy.call
146
+ end
147
+
148
+ def dispatch
149
+ response = @block_proxy.block.call(*@arguments)
150
+ @sender << BlockResponse.new(self, response)
151
+ end
152
+ end
153
+
106
154
  end
@@ -3,11 +3,30 @@ module Celluloid
3
3
 
4
4
  # ConditionVariable-like signaling between tasks and actors
5
5
  class Condition
6
+ class Waiter
7
+ def initialize(condition, task, mailbox)
8
+ @condition = condition
9
+ @task = task
10
+ @mailbox = mailbox
11
+ end
12
+ attr_reader :condition, :task
13
+
14
+ def <<(message)
15
+ @mailbox << message
16
+ end
17
+
18
+ def wait
19
+ message = @mailbox.receive do |msg|
20
+ msg.is_a?(SignalConditionRequest) && msg.task == Thread.current
21
+ end
22
+ message.value
23
+ end
24
+ end
25
+
6
26
  attr_reader :owner
7
27
 
8
28
  def initialize
9
29
  @mutex = Mutex.new
10
- @owner = Thread.current[:celluloid_actor]
11
30
  @tasks = []
12
31
  end
13
32
 
@@ -15,14 +34,18 @@ module Celluloid
15
34
  def wait
16
35
  raise ConditionError, "cannot wait for signals while exclusive" if Celluloid.exclusive?
17
36
 
37
+ if Thread.current[:celluloid_actor]
38
+ task = Task.current
39
+ else
40
+ task = Thread.current
41
+ end
42
+ waiter = Waiter.new(self, task, Celluloid.mailbox)
43
+
18
44
  @mutex.synchronize do
19
- actor = Thread.current[:celluloid_actor]
20
- raise ConditionError, "can't wait for conditions outside actors" unless actor
21
- raise ConditionError, "can't wait unless owner" unless actor == @owner
22
- @tasks << Task.current
45
+ @tasks << waiter
23
46
  end
24
47
 
25
- result = Task.suspend :condwait
48
+ result = Celluloid.suspend :condwait, waiter
26
49
  raise result if result.is_a? ConditionError
27
50
  result
28
51
  end
@@ -30,10 +53,8 @@ module Celluloid
30
53
  # Send a signal to the first task waiting on this condition
31
54
  def signal(value = nil)
32
55
  @mutex.synchronize do
33
- raise ConditionError, "no owner for this condition" unless @owner
34
-
35
- if task = @tasks.shift
36
- @owner.mailbox << SignalConditionRequest.new(task, value)
56
+ if waiter = @tasks.shift
57
+ waiter << SignalConditionRequest.new(waiter.task, value)
37
58
  else
38
59
  Logger.debug("Celluloid::Condition signaled spuriously")
39
60
  end
@@ -43,28 +64,11 @@ module Celluloid
43
64
  # Broadcast a value to all waiting tasks
44
65
  def broadcast(value = nil)
45
66
  @mutex.synchronize do
46
- raise ConditionError, "no owner for this condition" unless @owner
47
-
48
- @tasks.each { |task| @owner.mailbox << SignalConditionRequest.new(task, value) }
67
+ @tasks.each { |waiter| waiter << SignalConditionRequest.new(waiter.task, value) }
49
68
  @tasks.clear
50
69
  end
51
70
  end
52
71
 
53
- # Change the owner of this condition
54
- def owner=(actor)
55
- @mutex.synchronize do
56
- if @owner != actor
57
- @tasks.each do |task|
58
- ex = ConditionError.new("ownership changed")
59
- @owner.mailbox << SignalConditionRequest.new(task, ex)
60
- end
61
- @tasks.clear
62
- end
63
-
64
- @owner = actor
65
- end
66
- end
67
-
68
72
  alias_method :inspect, :to_s
69
73
  end
70
74
  end
@@ -1,20 +1,9 @@
1
1
  require 'celluloid/fiber'
2
2
 
3
- # Monkeypatch Thread to allow lazy access to its Celluloid::Mailbox
4
3
  class Thread
5
4
  attr_accessor :uuid_counter, :uuid_limit
6
5
 
7
- # Retrieve the mailbox for the current thread or lazily initialize it
8
- def self.mailbox
9
- current[:celluloid_mailbox] ||= Celluloid::Mailbox.new
6
+ def celluloid?
7
+ false
10
8
  end
11
-
12
- # Receive a message either as an actor or through the local mailbox
13
- def self.receive(timeout = nil, &block)
14
- if Celluloid.actor?
15
- Celluloid.receive(timeout, &block)
16
- else
17
- mailbox.receive(timeout, &block)
18
- end
19
- end
20
- end
9
+ end
@@ -12,7 +12,7 @@ module Celluloid
12
12
  Dir["/sys/devices/system/cpu/cpu*"].select { |n| n=~/cpu\d+/ }.count
13
13
  end
14
14
  when 'mingw', 'mswin'
15
- @cores = Integer(`SET NUMBER_OF_PROCESSORS`[/\d+/])
15
+ @cores = Integer(ENV["NUMBER_OF_PROCESSORS"][/\d+/])
16
16
  else
17
17
  @cores = nil
18
18
  end
@@ -0,0 +1,82 @@
1
+ module Celluloid
2
+ # An alternative implementation of Celluloid::Mailbox using Reactor
3
+ class EventedMailbox < Celluloid::Mailbox
4
+ attr_reader :reactor
5
+
6
+ def initialize(reactor_class)
7
+ super()
8
+ # @condition won't be used in the class.
9
+ @reactor = reactor_class.new
10
+ end
11
+
12
+ # Add a message to the Mailbox
13
+ def <<(message)
14
+ @mutex.lock
15
+ begin
16
+ if mailbox_full
17
+ Logger.debug "Discarded message: #{message}"
18
+ return
19
+ end
20
+ if message.is_a?(SystemEvent)
21
+ # Silently swallow system events sent to dead actors
22
+ return if @dead
23
+
24
+ # SystemEvents are high priority messages so they get added to the
25
+ # head of our message queue instead of the end
26
+ @messages.unshift message
27
+ else
28
+ raise MailboxError, "dead recipient" if @dead
29
+ @messages << message
30
+ end
31
+
32
+ current_actor = Thread.current[:celluloid_actor]
33
+ @reactor.wakeup unless current_actor && current_actor.mailbox == self
34
+ rescue IOError
35
+ raise MailboxError, "dead recipient"
36
+ ensure
37
+ @mutex.unlock rescue nil
38
+ end
39
+ nil
40
+ end
41
+
42
+ # Receive a message from the Mailbox
43
+ def receive(timeout = nil, &block)
44
+ message = next_message(block)
45
+
46
+ until message
47
+ if timeout
48
+ now = Time.now
49
+ wait_until ||= now + timeout
50
+ wait_interval = wait_until - now
51
+ return if wait_interval < 0
52
+ else
53
+ wait_interval = nil
54
+ end
55
+
56
+ @reactor.run_once(wait_interval)
57
+ message = next_message(block)
58
+ end
59
+
60
+ message
61
+ rescue IOError
62
+ shutdown # force shutdown of the mailbox
63
+ raise MailboxShutdown, "mailbox shutdown called during receive"
64
+ end
65
+
66
+ # Obtain the next message from the mailbox that matches the given block
67
+ def next_message(block)
68
+ @mutex.lock
69
+ begin
70
+ super(&block)
71
+ ensure
72
+ @mutex.unlock rescue nil
73
+ end
74
+ end
75
+
76
+ # Cleanup any IO objects this Mailbox may be using
77
+ def shutdown
78
+ @reactor.shutdown
79
+ super
80
+ end
81
+ end
82
+ end
data/lib/celluloid/fsm.rb CHANGED
@@ -62,6 +62,7 @@ module Celluloid
62
62
  # Be kind and call super if you must redefine initialize
63
63
  def initialize(actor = nil)
64
64
  @state = self.class.default_state
65
+ @delayed_transition = nil
65
66
  @actor = actor
66
67
  @actor ||= Celluloid.current_actor if Celluloid.actor?
67
68
  end
@@ -166,6 +167,7 @@ module Celluloid
166
167
 
167
168
  def initialize(name, transitions = nil, &block)
168
169
  @name, @block = name, block
170
+ @transitions = nil
169
171
  @transitions = Array(transitions).map { |t| t.to_sym } if transitions
170
172
  end
171
173
 
@@ -4,38 +4,30 @@ module Celluloid
4
4
  # Celluloid::Future objects allow methods and blocks to run in the
5
5
  # background, their values requested later
6
6
  class Future
7
+ def self.new(*args, &block)
8
+ return super unless block
9
+
10
+ future = new
11
+ Celluloid.internal_pool.get do
12
+ Thread.current.role = :future
13
+ begin
14
+ call = SyncCall.new(future, :call, args)
15
+ call.dispatch(block)
16
+ rescue
17
+ # Exceptions in blocks will get raised when the value is retrieved
18
+ end
19
+ end
20
+ future
21
+ end
22
+
7
23
  attr_reader :address
8
-
9
- # Create a future bound to a given receiver, or with a block to compute
10
- def initialize(*args, &block)
24
+
25
+ def initialize
11
26
  @address = Celluloid.uuid
12
27
  @mutex = Mutex.new
13
28
  @ready = false
14
29
  @result = nil
15
30
  @forwards = nil
16
-
17
- if block
18
- @call = SyncCall.new(self, :call, args)
19
- Celluloid.internal_pool.get do
20
- begin
21
- @call.dispatch(block)
22
- rescue
23
- # Exceptions in blocks will get raised when the value is retrieved
24
- end
25
- end
26
- else
27
- @call = nil
28
- end
29
- end
30
-
31
- # Execute the given method in future context
32
- def execute(receiver, method, args, block)
33
- @mutex.synchronize do
34
- raise "already calling" if @call
35
- @call = SyncCall.new(self, method, args, block)
36
- end
37
-
38
- receiver << @call
39
31
  end
40
32
 
41
33
  # Check if this future has a value yet
@@ -49,7 +41,6 @@ module Celluloid
49
41
 
50
42
  begin
51
43
  @mutex.lock
52
- raise "no call requested" unless @call
53
44
 
54
45
  if @ready
55
46
  ready = true
@@ -57,11 +48,11 @@ module Celluloid
57
48
  else
58
49
  case @forwards
59
50
  when Array
60
- @forwards << Thread.mailbox
51
+ @forwards << Celluloid.mailbox
61
52
  when NilClass
62
- @forwards = Thread.mailbox
53
+ @forwards = Celluloid.mailbox
63
54
  else
64
- @forwards = [@forwards, Thread.mailbox]
55
+ @forwards = [@forwards, Celluloid.mailbox]
65
56
  end
66
57
  end
67
58
  ensure
@@ -69,7 +60,7 @@ module Celluloid
69
60
  end
70
61
 
71
62
  unless ready
72
- result = Thread.receive(timeout) do |msg|
63
+ result = Celluloid.receive(timeout) do |msg|
73
64
  msg.is_a?(Future::Result) && msg.future == self
74
65
  end
75
66
  end
@@ -10,6 +10,10 @@ module Celluloid
10
10
  @mutex = Mutex.new
11
11
  @busy_size = @idle_size = 0
12
12
 
13
+ reset
14
+ end
15
+
16
+ def reset
13
17
  # TODO: should really adjust this based on usage
14
18
  @max_idle = 16
15
19
  end
@@ -74,6 +78,15 @@ module Celluloid
74
78
  thread[key] = nil
75
79
  end
76
80
  end
81
+
82
+ def shutdown
83
+ @mutex.synchronize do
84
+ @max_idle = 0
85
+ @pool.each do |thread|
86
+ thread[:celluloid_queue] << nil
87
+ end
88
+ end
89
+ end
77
90
  end
78
91
 
79
92
  self.internal_pool = InternalPool.new