celluloid 0.17.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of celluloid might be problematic. Click here for more details.

Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +10 -2
  3. data/LICENSE.txt +1 -1
  4. data/README.md +26 -14
  5. data/culture/gems/dependencies.yml +8 -2
  6. data/examples/stack.rb +47 -0
  7. data/lib/celluloid.rb +9 -6
  8. data/lib/celluloid/actor.rb +7 -32
  9. data/lib/celluloid/actor/manager.rb +7 -0
  10. data/lib/celluloid/actor/system.rb +163 -0
  11. data/lib/celluloid/call/sync.rb +1 -1
  12. data/lib/celluloid/calls.rb +3 -3
  13. data/lib/celluloid/cell.rb +1 -1
  14. data/lib/celluloid/condition.rb +3 -4
  15. data/lib/celluloid/debug.rb +1 -0
  16. data/lib/celluloid/deprecate.rb +3 -0
  17. data/lib/celluloid/exceptions.rb +20 -15
  18. data/lib/celluloid/future.rb +40 -3
  19. data/lib/celluloid/group.rb +5 -9
  20. data/lib/celluloid/group/pool.rb +1 -1
  21. data/lib/celluloid/group/spawner.rb +1 -2
  22. data/lib/celluloid/mailbox.rb +2 -2
  23. data/lib/celluloid/managed.rb +3 -0
  24. data/lib/celluloid/notices.rb +1 -1
  25. data/lib/celluloid/proxies.rb +7 -8
  26. data/lib/celluloid/proxy/abstract.rb +16 -21
  27. data/lib/celluloid/proxy/actor.rb +33 -37
  28. data/lib/celluloid/proxy/async.rb +24 -29
  29. data/lib/celluloid/proxy/block.rb +20 -24
  30. data/lib/celluloid/proxy/cell.rb +58 -62
  31. data/lib/celluloid/proxy/future.rb +33 -37
  32. data/lib/celluloid/proxy/sync.rb +31 -35
  33. data/lib/celluloid/system_events.rb +53 -1
  34. data/lib/celluloid/task.rb +13 -21
  35. data/lib/celluloid/task/fibered.rb +1 -1
  36. data/lib/celluloid/task/threaded.rb +2 -2
  37. data/lib/celluloid/version.rb +1 -1
  38. data/spec/celluloid/{group → actor}/manager_spec.rb +0 -0
  39. data/spec/celluloid/{actor_system_spec.rb → actor/system_spec.rb} +4 -4
  40. data/spec/celluloid/block_spec.rb +64 -3
  41. data/spec/celluloid/condition_spec.rb +6 -0
  42. data/spec/celluloid/future_spec.rb +2 -2
  43. data/spec/deprecate/actor_system_spec.rb +1 -1
  44. data/spec/deprecate/future_spec.rb +2 -2
  45. data/spec/shared/actor_examples.rb +20 -4
  46. data/spec/shared/group_examples.rb +1 -1
  47. data/spec/shared/mailbox_examples.rb +1 -1
  48. data/spec/spec_helper.rb +3 -3
  49. metadata +110 -76
  50. data/lib/celluloid/actor_system.rb +0 -160
  51. data/lib/celluloid/group/manager.rb +0 -27
@@ -15,7 +15,7 @@ module Celluloid
15
15
  Internals::CallChain.current_id = @chain_id
16
16
  result = super(obj)
17
17
  respond Internals::Response::Success.new(self, result)
18
- rescue Exception => ex
18
+ rescue ::Exception => ex
19
19
  # Exceptions that occur during synchronous calls are reraised in the
20
20
  # context of the sender
21
21
  respond Internals::Response::Error.new(self, ex)
@@ -12,7 +12,7 @@ module Celluloid
12
12
  # FIXME: nicer exception
13
13
  fail "Cannot execute blocks on sender in exclusive mode"
14
14
  end
15
- @block = Proxy::Block.new(self, Celluloid.mailbox, block)
15
+ @block = Proxy::Block.new(Celluloid.mailbox, self, block)
16
16
  else
17
17
  @block = nil
18
18
  end
@@ -26,10 +26,10 @@ module Celluloid
26
26
  check(obj)
27
27
  _b = @block && @block.to_proc
28
28
  obj.public_send(@method, *@arguments, &_b)
29
- # rescue Celluloid::TimeoutError => ex
29
+ # rescue Celluloid::TaskTimeout => ex
30
30
  # raise ex unless ( @retry += 1 ) <= RETRY_CALL_LIMIT
31
31
  # puts "retrying"
32
- # Internals::Logger.warn("TimeoutError at Call dispatch. Retrying in #{RETRY_CALL_WAIT} seconds. ( Attempt #{@retry} of #{RETRY_CALL_LIMIT} )")
32
+ # Internals::Logger.warn("TaskTimeout at Call dispatch. Retrying in #{RETRY_CALL_WAIT} seconds. ( Attempt #{@retry} of #{RETRY_CALL_LIMIT} )")
33
33
  # sleep RETRY_CALL_WAIT
34
34
  # retry
35
35
  end
@@ -41,7 +41,7 @@ module Celluloid
41
41
  end
42
42
 
43
43
  @actor.start
44
- @proxy = (options[:proxy_class] || Proxy::Cell).new(@actor.proxy, @actor.mailbox, @subject.class.to_s)
44
+ @proxy = (options[:proxy_class] || Proxy::Cell).new(@actor.mailbox, @actor.proxy, @subject.class.to_s)
45
45
  end
46
46
  attr_reader :proxy, :subject
47
47
 
@@ -1,6 +1,4 @@
1
1
  module Celluloid
2
- class ConditionError < Celluloid::Error; end
3
-
4
2
  # ConditionVariable-like signaling between tasks and threads
5
3
  class Condition
6
4
  class Waiter
@@ -21,7 +19,7 @@ module Celluloid
21
19
  message = @mailbox.receive(@timeout) do |msg|
22
20
  msg.is_a?(SignalConditionRequest) && msg.task == Thread.current
23
21
  end
24
- rescue TimeoutError
22
+ rescue TimedOut
25
23
  raise ConditionError, "timeout after #{@timeout.inspect} seconds"
26
24
  end until message
27
25
 
@@ -59,7 +57,8 @@ module Celluloid
59
57
 
60
58
  result = Celluloid.suspend :condwait, waiter
61
59
  timer.cancel if timer
62
- fail result if result.is_a? ConditionError
60
+ fail result if result.is_a?(ConditionError)
61
+ return yield(result) if block_given?
63
62
  result
64
63
  end
65
64
 
@@ -0,0 +1 @@
1
+ $CELLULOID_DEBUG = true
@@ -15,4 +15,7 @@ module Celluloid
15
15
  InternalPool = Group::Pool
16
16
  TaskThread = Task::Threaded
17
17
  TaskFiber = Task::Fibered
18
+ ActorSystem = Actor::System
19
+ Task::TerminatedError = TaskTerminated
20
+ Task::TimeoutError = TaskTimeout
18
21
  end
@@ -1,23 +1,28 @@
1
1
  module Celluloid
2
- # Base class of all Celluloid errors
3
- Error = Class.new(StandardError)
4
-
5
- # Don't do Actor-like things outside Actor scope
6
- NotActorError = Class.new(Celluloid::Error)
7
-
8
- # Trying to do something to a dead actor
9
- DeadActorError = Class.new(Celluloid::Error)
10
-
11
- # A timeout occured before the given request could complete
12
- TimeoutError = Class.new(Celluloid::Error)
13
-
14
- # The sender made an error, not the current actor
15
- class AbortError < Celluloid::Error
2
+ class Error < StandardError; end
3
+ class Interruption < Exception; end
4
+ class TimedOut < Celluloid::Interruption; end # Distinguished from `Timeout`
5
+ class StillActive < Celluloid::Error; end
6
+ class NotActive < Celluloid::Error; end
7
+ class NotActorError < Celluloid::Error; end # Don't do Actor-like things outside Actor scope
8
+ class DeadActorError < Celluloid::Error; end # Trying to do something to a dead actor
9
+ class NotTaskError < Celluloid::Error; end # Asked to do task-related things outside a task
10
+ class DeadTaskError < Celluloid::Error; end # Trying to resume a dead task
11
+ class TaskTerminated < Celluloid::Interruption; end # Kill a running task after terminate
12
+ class TaskTimeout < Celluloid::TimedOut; end # A timeout occured before the given request could complete
13
+ class ConditionError < Celluloid::Error; end
14
+ class AbortError < Celluloid::Error # The sender made an error, not the current actor
16
15
  attr_reader :cause
17
-
18
16
  def initialize(cause)
19
17
  @cause = cause
20
18
  super "caused by #{cause.inspect}: #{cause}"
21
19
  end
22
20
  end
21
+ module Feature
22
+ module Requires
23
+ class RubiniusOrJRuby < Celluloid::Error; end
24
+ class Rubinius < Celluloid::Error; end
25
+ class JRuby < Celluloid::Error; end
26
+ end
27
+ end
23
28
  end
@@ -8,8 +8,12 @@ module Celluloid
8
8
  return super unless block
9
9
 
10
10
  future = new
11
+ task = Thread.current[:celluloid_task]
12
+ actor = Thread.current[:celluloid_actor]
11
13
  Internals::ThreadHandle.new(Celluloid.actor_system, :future) do
12
14
  begin
15
+ Thread.current[:celluloid_task] = task
16
+ Thread.current[:celluloid_actor] = actor
13
17
  call = Call::Sync.new(future, :call, args)
14
18
  call.dispatch(block)
15
19
  rescue
@@ -21,12 +25,36 @@ module Celluloid
21
25
 
22
26
  attr_reader :address
23
27
 
24
- def initialize
28
+ def initialize(&block)
25
29
  @address = Celluloid.uuid
26
30
  @mutex = Mutex.new
27
31
  @ready = false
28
32
  @result = nil
29
33
  @forwards = nil
34
+ @cancelled = false
35
+
36
+ if block
37
+ @call = Call::Sync.new(self, :call, args)
38
+ Celluloid.internal_pool.get do
39
+ begin
40
+ @call.dispatch(block)
41
+ rescue
42
+ # Exceptions in blocks will get raised when the value is retrieved
43
+ end
44
+ end
45
+ else
46
+ @call = nil
47
+ end
48
+ end
49
+
50
+ # Execute the given method in future context
51
+ def execute(receiver, method, args, block)
52
+ @mutex.synchronize do
53
+ fail "already calling" if @call
54
+ @call = Call::Sync.new(self, method, args, block)
55
+ end
56
+
57
+ receiver << @call
30
58
  end
31
59
 
32
60
  # Check if this future has a value yet
@@ -65,15 +93,16 @@ module Celluloid
65
93
  end
66
94
 
67
95
  if result
68
- result.value
96
+ (result.respond_to?(:value)) ? result.value : result
69
97
  else
70
- fail TimeoutError, "Timed out"
98
+ fail TimedOut, "Timed out"
71
99
  end
72
100
  end
73
101
  alias_method :call, :value
74
102
 
75
103
  # Signal this future with the given result value
76
104
  def signal(value)
105
+ return if @cancelled
77
106
  result = Result.new(value, self)
78
107
 
79
108
  @mutex.synchronize do
@@ -89,6 +118,14 @@ module Celluloid
89
118
  end
90
119
  alias_method :<<, :signal
91
120
 
121
+ def cancel(error)
122
+ response = ErrorResponse.new(@call, error)
123
+ signal response
124
+ @mutex.synchronize do
125
+ @cancelled = true
126
+ end
127
+ end
128
+
92
129
  # Inspect this Celluloid::Future
93
130
  alias_method :inspect, :to_s
94
131
 
@@ -1,9 +1,5 @@
1
1
  module Celluloid
2
2
  class Group
3
- class NotImplemented < StandardError; end
4
- class StillActive < StandardError; end
5
- class NotActive < StandardError; end
6
-
7
3
  attr_accessor :group
8
4
 
9
5
  def initialize
@@ -13,7 +9,7 @@ module Celluloid
13
9
  end
14
10
 
15
11
  def assert_active
16
- fail NotActive unless active?
12
+ fail Celluloid::NotActive unless active?
17
13
  end
18
14
 
19
15
  def assert_inactive
@@ -21,7 +17,7 @@ module Celluloid
21
17
  if RUBY_PLATFORM == "java"
22
18
  Celluloid.logger.warn "Group is still active"
23
19
  else
24
- fail StillActive
20
+ fail Celluloid::StillActive
25
21
  end
26
22
  end
27
23
 
@@ -51,15 +47,15 @@ module Celluloid
51
47
  end
52
48
 
53
49
  def get
54
- fail NotImplemented
50
+ fail NotImplementedError
55
51
  end
56
52
 
57
53
  def create
58
- fail NotImplemented
54
+ fail NotImplementedError
59
55
  end
60
56
 
61
57
  def shutdown
62
- fail NotImplemented
58
+ fail NotImplementedError
63
59
  end
64
60
  end
65
61
  end
@@ -93,7 +93,7 @@ module Celluloid
93
93
  while proc = queue.pop
94
94
  begin
95
95
  proc.call
96
- rescue Exception => ex
96
+ rescue ::Exception => ex
97
97
  Internals::Logger.crash("thread crashed", ex)
98
98
  ensure
99
99
  put thread
@@ -25,7 +25,6 @@ module Celluloid
25
25
  th.kill
26
26
  queue << th
27
27
  end
28
-
29
28
  loop do
30
29
  break if queue.empty?
31
30
  queue.pop.join
@@ -52,7 +51,7 @@ module Celluloid
52
51
 
53
52
  begin
54
53
  proc.call
55
- rescue Exception => ex
54
+ rescue ::Exception => ex
56
55
  Internals::Logger.crash("thread crashed", ex)
57
56
  Thread.current[:celluloid_meta][:state] = :error
58
57
  ensure
@@ -70,7 +70,7 @@ module Celluloid
70
70
  end
71
71
 
72
72
  # Receive a letter from the mailbox. Guaranteed to return a message. If
73
- # timeout is exceeded, raise a TimeoutError.
73
+ # timeout is exceeded, raise a TaskTimeout.
74
74
  def receive(timeout = nil, &block)
75
75
  message = nil
76
76
  Timers::Wait.for(timeout) do |remaining|
@@ -78,7 +78,7 @@ module Celluloid
78
78
  break if message
79
79
  end
80
80
  return message if message
81
- fail TimeoutError.new("receive timeout exceeded")
81
+ fail TaskTimeout.new("receive timeout exceeded")
82
82
  end
83
83
 
84
84
  # Shut down this mailbox and clean up its contents
@@ -0,0 +1,3 @@
1
+ $CELLULOID_BACKPORTED = false
2
+ $CELLULOID_MANAGED = true
3
+ require "celluloid/autostart"
@@ -4,7 +4,7 @@ module Celluloid
4
4
  @@notices = []
5
5
 
6
6
  def backported
7
- @@notices << [:debug, "Celluloid #{Celluloid::VERSION} is running in BACKPORTED mode. [ http://git.io/vJf3J ]"]
7
+ @@notices << [:info, "Celluloid #{Celluloid::VERSION} is running in BACKPORTED mode. [ http://git.io/vJf3J ]"]
8
8
  end
9
9
 
10
10
  def output
@@ -1,12 +1,11 @@
1
1
  module Celluloid
2
2
  module Proxy
3
+ require "celluloid/proxy/abstract"
4
+ require "celluloid/proxy/sync"
5
+ require "celluloid/proxy/cell"
6
+ require "celluloid/proxy/actor"
7
+ require "celluloid/proxy/async"
8
+ require "celluloid/proxy/future"
9
+ require "celluloid/proxy/block"
3
10
  end
4
11
  end
5
-
6
- require "celluloid/proxy/abstract"
7
- require "celluloid/proxy/sync"
8
- require "celluloid/proxy/cell"
9
- require "celluloid/proxy/actor"
10
- require "celluloid/proxy/async"
11
- require "celluloid/proxy/future"
12
- require "celluloid/proxy/block"
@@ -1,24 +1,19 @@
1
- module Celluloid
2
- module Proxy
3
- # Base class of all Celluloid proxies
4
- class Abstract < BasicObject
5
- # Used for reflecting on proxy objects themselves
6
- def __class__
7
- Proxy::Abstract
8
- end
9
-
10
- # Needed for storing proxies in data structures
11
- needed = [:object_id, :__id__, :hash, :private_methods] - instance_methods
12
- if needed.any?
13
- include ::Kernel.dup.module_eval {
14
- undef_method(*(instance_methods - needed))
15
- self
16
- }
1
+ # Base class of Celluloid proxies
2
+ class Celluloid::Proxy::Abstract < BasicObject
3
+ # Used for reflecting on proxy objects themselves
4
+ def __class__
5
+ ::Celluloid::Proxy::Abstract
6
+ end
17
7
 
18
- # rubinius bug? These methods disappear when we include hacked kernel
19
- define_method :==, ::BasicObject.instance_method(:==) unless instance_methods.include?(:==)
20
- alias_method(:equal?, :==) unless instance_methods.include?(:equal?)
21
- end
22
- end
8
+ # Needed for storing proxies in data structures
9
+ needed = [:object_id, :__id__, :hash, :private_methods] - instance_methods
10
+ if needed.any?
11
+ include ::Kernel.dup.module_eval {
12
+ undef_method(*(instance_methods - needed))
13
+ self
14
+ }
15
+ # rubinius bug? These methods disappear when we include hacked kernel
16
+ define_method :==, ::BasicObject.instance_method(:==) unless instance_methods.include?(:==)
17
+ alias_method(:equal?, :==) unless instance_methods.include?(:equal?)
23
18
  end
24
19
  end
@@ -1,46 +1,42 @@
1
- module Celluloid
2
- module Proxy
3
- # A proxy which controls the Actor lifecycle
4
- class Actor < Abstract
5
- attr_reader :thread, :mailbox
1
+ # A proxy which controls the Actor lifecycle
2
+ class Celluloid::Proxy::Actor < Celluloid::Proxy::Abstract
3
+ attr_reader :thread, :mailbox
6
4
 
7
- # Used for reflecting on proxy objects themselves
8
- def __class__
9
- Proxy::Actor
10
- end
5
+ # Used for reflecting on proxy objects themselves
6
+ def __class__
7
+ ::Celluloid::Proxy::Actor
8
+ end
11
9
 
12
- def initialize(thread, mailbox)
13
- @thread = thread
14
- @mailbox = mailbox
15
- end
10
+ def initialize(mailbox, thread)
11
+ @mailbox = mailbox
12
+ @thread = thread
13
+ end
16
14
 
17
- def inspect
18
- # TODO: use a system event to fetch actor state: tasks?
19
- "#<Celluloid::Proxy::Actor(#{@mailbox.address}) alive>"
20
- rescue DeadActorError
21
- "#<Celluloid::Proxy::Actor(#{@mailbox.address}) dead>"
22
- end
15
+ def inspect
16
+ # TODO: use a system event to fetch actor state: tasks?
17
+ "#<Celluloid::Proxy::Actor(#{@mailbox.address}) alive>"
18
+ rescue DeadActorError
19
+ "#<Celluloid::Proxy::Actor(#{@mailbox.address}) dead>"
20
+ end
23
21
 
24
- def alive?
25
- @mailbox.alive?
26
- end
22
+ def alive?
23
+ @mailbox.alive?
24
+ end
27
25
 
28
- def dead?
29
- !alive?
30
- end
26
+ def dead?
27
+ !alive?
28
+ end
31
29
 
32
- # Terminate the associated actor
33
- def terminate
34
- terminate!
35
- ::Celluloid::Actor.join(self)
36
- nil
37
- end
30
+ # Terminate the associated actor
31
+ def terminate
32
+ terminate!
33
+ ::Celluloid::Actor.join(self)
34
+ nil
35
+ end
38
36
 
39
- # Terminate the associated actor asynchronously
40
- def terminate!
41
- ::Kernel.raise DeadActorError, "actor already terminated" unless alive?
42
- @mailbox << TerminationRequest.new
43
- end
44
- end
37
+ # Terminate the associated actor asynchronously
38
+ def terminate!
39
+ ::Kernel.raise ::Celluloid::DeadActorError, "actor already terminated" unless alive?
40
+ @mailbox << ::Celluloid::TerminationRequest.new
45
41
  end
46
42
  end