celluloid 0.16.0 → 0.17.3

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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +394 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +28 -15
  5. data/culture/CONDUCT.md +28 -0
  6. data/culture/Gemfile +9 -0
  7. data/culture/LICENSE.txt +22 -0
  8. data/culture/README.md +22 -0
  9. data/culture/Rakefile +5 -0
  10. data/culture/SYNC.md +70 -0
  11. data/culture/celluloid-culture.gemspec +18 -0
  12. data/culture/gems/README.md +39 -0
  13. data/culture/gems/dependencies.yml +85 -0
  14. data/culture/gems/loader.rb +101 -0
  15. data/culture/rubocop/README.md +38 -0
  16. data/culture/rubocop/lint.yml +8 -0
  17. data/culture/rubocop/metrics.yml +15 -0
  18. data/culture/rubocop/perf.yml +0 -0
  19. data/culture/rubocop/rubocop.yml +5 -0
  20. data/culture/rubocop/style.yml +57 -0
  21. data/culture/spec/gems_spec.rb +2 -0
  22. data/culture/spec/spec_helper.rb +0 -0
  23. data/culture/spec/sync_spec.rb +2 -0
  24. data/culture/sync.rb +56 -0
  25. data/culture/tasks/rspec.rake +5 -0
  26. data/culture/tasks/rubocop.rake +2 -0
  27. data/examples/basic_usage.rb +49 -0
  28. data/examples/futures.rb +38 -0
  29. data/examples/ring.rb +61 -0
  30. data/examples/simple_pmap.rb +14 -0
  31. data/examples/stack.rb +47 -0
  32. data/examples/timers.rb +72 -0
  33. data/lib/celluloid/actor/manager.rb +7 -0
  34. data/lib/celluloid/actor/system.rb +163 -0
  35. data/lib/celluloid/actor.rb +53 -71
  36. data/lib/celluloid/autostart.rb +1 -1
  37. data/lib/celluloid/backported.rb +2 -0
  38. data/lib/celluloid/call/async.rb +16 -0
  39. data/lib/celluloid/call/block.rb +22 -0
  40. data/lib/celluloid/call/sync.rb +70 -0
  41. data/lib/celluloid/calls.rb +24 -114
  42. data/lib/celluloid/cell.rb +32 -20
  43. data/lib/celluloid/condition.rb +5 -6
  44. data/lib/celluloid/core_ext.rb +1 -1
  45. data/lib/celluloid/current.rb +2 -0
  46. data/lib/celluloid/debug.rb +1 -0
  47. data/lib/celluloid/deprecate.rb +21 -0
  48. data/lib/celluloid/exceptions.rb +22 -16
  49. data/lib/celluloid/fiber.rb +3 -3
  50. data/lib/celluloid/future.rb +46 -8
  51. data/lib/celluloid/group/pool.rb +125 -0
  52. data/lib/celluloid/group/spawner.rb +68 -0
  53. data/lib/celluloid/group.rb +61 -0
  54. data/lib/celluloid/logging.rb +5 -5
  55. data/lib/celluloid/mailbox/evented.rb +74 -0
  56. data/lib/celluloid/mailbox.rb +15 -14
  57. data/lib/celluloid/managed.rb +3 -0
  58. data/lib/celluloid/notices.rb +15 -0
  59. data/lib/celluloid/proxies.rb +11 -0
  60. data/lib/celluloid/proxy/abstract.rb +50 -0
  61. data/lib/celluloid/proxy/actor.rb +37 -0
  62. data/lib/celluloid/proxy/async.rb +15 -0
  63. data/lib/celluloid/proxy/block.rb +28 -0
  64. data/lib/celluloid/proxy/cell.rb +66 -0
  65. data/lib/celluloid/proxy/future.rb +20 -0
  66. data/lib/celluloid/proxy/sync.rb +24 -0
  67. data/lib/celluloid/rspec.rb +67 -9
  68. data/lib/celluloid/system_events.rb +69 -14
  69. data/lib/celluloid/task/fibered.rb +45 -0
  70. data/lib/celluloid/task/threaded.rb +59 -0
  71. data/lib/celluloid/{tasks.rb → task.rb} +30 -38
  72. data/lib/celluloid/test.rb +1 -1
  73. data/lib/celluloid/thread.rb +6 -1
  74. data/lib/celluloid/version.rb +3 -0
  75. data/lib/celluloid.rb +151 -130
  76. data/spec/celluloid/actor/system_spec.rb +83 -0
  77. data/spec/celluloid/actor_spec.rb +2 -2
  78. data/spec/celluloid/block_spec.rb +67 -8
  79. data/spec/celluloid/calls_spec.rb +28 -23
  80. data/spec/celluloid/condition_spec.rb +23 -14
  81. data/spec/celluloid/evented_mailbox_spec.rb +1 -31
  82. data/spec/celluloid/future_spec.rb +15 -12
  83. data/spec/celluloid/group/elastic_spec.rb +0 -0
  84. data/spec/celluloid/group/pool_spec.rb +8 -0
  85. data/spec/celluloid/group/spawner_spec.rb +17 -0
  86. data/spec/celluloid/mailbox/evented_spec.rb +40 -0
  87. data/spec/celluloid/mailbox_spec.rb +1 -3
  88. data/spec/celluloid/misc/leak_spec.rb +73 -0
  89. data/spec/celluloid/proxy_spec.rb +33 -0
  90. data/spec/celluloid/task/fibered_spec.rb +5 -0
  91. data/spec/celluloid/task/threaded_spec.rb +5 -0
  92. data/spec/celluloid/timer_spec.rb +14 -16
  93. data/spec/deprecate/actor_system_spec.rb +72 -0
  94. data/spec/deprecate/block_spec.rb +52 -0
  95. data/spec/deprecate/calls_spec.rb +39 -0
  96. data/spec/deprecate/evented_mailbox_spec.rb +34 -0
  97. data/spec/deprecate/future_spec.rb +32 -0
  98. data/spec/deprecate/internal_pool_spec.rb +4 -0
  99. data/spec/shared/actor_examples.rb +1259 -0
  100. data/spec/shared/group_examples.rb +121 -0
  101. data/spec/shared/mailbox_examples.rb +87 -0
  102. data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
  103. data/spec/spec_helper.rb +5 -42
  104. data/spec/support/configure_rspec.rb +77 -0
  105. data/spec/support/coverage.rb +4 -0
  106. data/spec/support/crash_checking.rb +68 -0
  107. data/spec/support/debugging.rb +31 -0
  108. data/spec/support/env.rb +21 -0
  109. data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
  110. data/spec/support/examples/call_class.rb +37 -0
  111. data/spec/support/examples/evented_mailbox_class.rb +27 -0
  112. data/spec/support/includer.rb +6 -0
  113. data/spec/support/logging.rb +55 -0
  114. data/spec/support/loose_threads.rb +68 -0
  115. data/spec/support/reset_class_variables.rb +27 -0
  116. data/spec/support/sleep_and_wait.rb +14 -0
  117. data/spec/support/stubbing.rb +14 -0
  118. metadata +276 -78
  119. data/lib/celluloid/actor_system.rb +0 -107
  120. data/lib/celluloid/call_chain.rb +0 -13
  121. data/lib/celluloid/cpu_counter.rb +0 -34
  122. data/lib/celluloid/evented_mailbox.rb +0 -73
  123. data/lib/celluloid/fsm.rb +0 -186
  124. data/lib/celluloid/handlers.rb +0 -41
  125. data/lib/celluloid/internal_pool.rb +0 -159
  126. data/lib/celluloid/legacy.rb +0 -9
  127. data/lib/celluloid/links.rb +0 -36
  128. data/lib/celluloid/logger.rb +0 -93
  129. data/lib/celluloid/logging/incident.rb +0 -21
  130. data/lib/celluloid/logging/incident_logger.rb +0 -129
  131. data/lib/celluloid/logging/incident_reporter.rb +0 -48
  132. data/lib/celluloid/logging/log_event.rb +0 -20
  133. data/lib/celluloid/logging/ring_buffer.rb +0 -65
  134. data/lib/celluloid/method.rb +0 -32
  135. data/lib/celluloid/notifications.rb +0 -83
  136. data/lib/celluloid/pool_manager.rb +0 -146
  137. data/lib/celluloid/probe.rb +0 -73
  138. data/lib/celluloid/properties.rb +0 -24
  139. data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
  140. data/lib/celluloid/proxies/actor_proxy.rb +0 -38
  141. data/lib/celluloid/proxies/async_proxy.rb +0 -31
  142. data/lib/celluloid/proxies/block_proxy.rb +0 -29
  143. data/lib/celluloid/proxies/cell_proxy.rb +0 -68
  144. data/lib/celluloid/proxies/future_proxy.rb +0 -35
  145. data/lib/celluloid/proxies/sync_proxy.rb +0 -36
  146. data/lib/celluloid/receivers.rb +0 -63
  147. data/lib/celluloid/registry.rb +0 -57
  148. data/lib/celluloid/responses.rb +0 -44
  149. data/lib/celluloid/rspec/actor_examples.rb +0 -1054
  150. data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
  151. data/lib/celluloid/signals.rb +0 -23
  152. data/lib/celluloid/stack_dump.rb +0 -133
  153. data/lib/celluloid/supervision_group.rb +0 -169
  154. data/lib/celluloid/supervisor.rb +0 -22
  155. data/lib/celluloid/task_set.rb +0 -49
  156. data/lib/celluloid/tasks/task_fiber.rb +0 -43
  157. data/lib/celluloid/tasks/task_thread.rb +0 -53
  158. data/lib/celluloid/thread_handle.rb +0 -50
  159. data/lib/celluloid/uuid.rb +0 -38
  160. data/spec/celluloid/actor_system_spec.rb +0 -69
  161. data/spec/celluloid/cpu_counter_spec.rb +0 -82
  162. data/spec/celluloid/fsm_spec.rb +0 -107
  163. data/spec/celluloid/internal_pool_spec.rb +0 -52
  164. data/spec/celluloid/links_spec.rb +0 -45
  165. data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
  166. data/spec/celluloid/notifications_spec.rb +0 -120
  167. data/spec/celluloid/pool_spec.rb +0 -92
  168. data/spec/celluloid/probe_spec.rb +0 -121
  169. data/spec/celluloid/properties_spec.rb +0 -42
  170. data/spec/celluloid/registry_spec.rb +0 -64
  171. data/spec/celluloid/stack_dump_spec.rb +0 -64
  172. data/spec/celluloid/supervision_group_spec.rb +0 -65
  173. data/spec/celluloid/supervisor_spec.rb +0 -103
  174. data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
  175. data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
  176. data/spec/celluloid/thread_handle_spec.rb +0 -26
  177. data/spec/celluloid/uuid_spec.rb +0 -11
@@ -0,0 +1,68 @@
1
+ require "thread"
2
+
3
+ module Celluloid
4
+ class Group
5
+ class Spawner < Group
6
+ attr_accessor :finalizer
7
+
8
+ def initialize
9
+ super
10
+ end
11
+
12
+ def get(&block)
13
+ assert_active
14
+ fail ArgumentError.new("No block sent to Spawner.get()") unless block_given?
15
+ instantiate block
16
+ end
17
+
18
+ def shutdown
19
+ @running = false
20
+ queue = []
21
+ @mutex.synchronize do
22
+ loop do
23
+ break if @group.empty?
24
+ th = @group.shift
25
+ th.kill
26
+ queue << th
27
+ end
28
+ end
29
+ Thread.pass unless queue.empty?
30
+ loop do
31
+ break if queue.empty?
32
+ queue.pop.join
33
+ end
34
+ end
35
+
36
+ def idle?
37
+ to_a.select { |t| t[:celluloid_thread_state] == :running }.empty?
38
+ end
39
+
40
+ def busy?
41
+ to_a.select { |t| t[:celluloid_thread_state] == :running }.any?
42
+ end
43
+
44
+ private
45
+
46
+ def instantiate(proc)
47
+ thread = Thread.new do
48
+ Thread.current[:celluloid_thread_state] = :running
49
+ begin
50
+ proc.call
51
+ rescue ::Exception => ex
52
+ Internals::Logger.crash("thread crashed", ex)
53
+ Thread.current[:celluloid_thread_state] = :error
54
+ ensure
55
+ unless Thread.current[:celluloid_thread_state] == :error
56
+ Thread.current[:celluloid_thread_state] = :finished
57
+ end
58
+ @mutex.synchronize { @group.delete Thread.current }
59
+ Thread.exit
60
+ end
61
+ end
62
+
63
+ @mutex.synchronize { @group << thread }
64
+ thread
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,61 @@
1
+ module Celluloid
2
+ class Group
3
+ attr_accessor :group
4
+
5
+ def initialize
6
+ @mutex = Mutex.new
7
+ @group = []
8
+ @running = true
9
+ end
10
+
11
+ def assert_active
12
+ fail Celluloid::NotActive unless active?
13
+ end
14
+
15
+ def assert_inactive
16
+ return unless active?
17
+ if RUBY_PLATFORM == "java"
18
+ Celluloid.logger.warn "Group is still active"
19
+ else
20
+ fail Celluloid::StillActive
21
+ end
22
+ end
23
+
24
+ def each
25
+ to_a.each { |thread| yield thread }
26
+ end
27
+
28
+ def to_a
29
+ res = nil
30
+ @mutex.synchronize { res = @group.dup }
31
+ res
32
+ end
33
+
34
+ def purge(thread)
35
+ @mutex.synchronize do
36
+ @group.delete(thread)
37
+ thread.kill rescue nil
38
+ end
39
+ end
40
+
41
+ def each_actor(&block)
42
+ to_a.lazy.select { |t| t[:celluloid_role] == :actor }.each(&block)
43
+ end
44
+
45
+ def active?
46
+ @running
47
+ end
48
+
49
+ def get
50
+ fail NotImplementedError
51
+ end
52
+
53
+ def create
54
+ fail NotImplementedError
55
+ end
56
+
57
+ def shutdown
58
+ fail NotImplementedError
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
- require 'celluloid/logging/log_event'
2
- require 'celluloid/logging/incident'
3
- require 'celluloid/logging/ring_buffer'
4
- require 'celluloid/logging/incident_logger'
5
- require 'celluloid/logging/incident_reporter'
1
+ require "celluloid/logging/log_event"
2
+ require "celluloid/logging/incident"
3
+ require "celluloid/logging/ring_buffer"
4
+ require "celluloid/logging/incident_logger"
5
+ require "celluloid/logging/incident_reporter"
@@ -0,0 +1,74 @@
1
+ module Celluloid
2
+ class Mailbox
3
+ # An alternative implementation of Celluloid::Mailbox using Reactor
4
+ class Evented < Celluloid::Mailbox
5
+ attr_reader :reactor
6
+
7
+ def initialize(reactor_class)
8
+ super()
9
+ # @condition won't be used in the class.
10
+ @reactor = reactor_class.new
11
+ end
12
+
13
+ # Add a message to the Mailbox
14
+ def <<(message)
15
+ @mutex.lock
16
+ begin
17
+ if mailbox_full || @dead
18
+ dead_letter(message)
19
+ return
20
+ end
21
+ if message.is_a?(SystemEvent)
22
+ # SystemEvents are high priority messages so they get added to the
23
+ # head of our message queue instead of the end
24
+ @messages.unshift message
25
+ else
26
+ @messages << message
27
+ end
28
+ ensure
29
+ @mutex.unlock rescue nil
30
+ end
31
+ begin
32
+ current_actor = Thread.current[:celluloid_actor]
33
+ @reactor.wakeup unless current_actor && current_actor.mailbox == self
34
+ rescue
35
+ Internals::Logger.crash "reactor crashed", $ERROR_INFO
36
+ dead_letter(message)
37
+ end
38
+ nil
39
+ end
40
+
41
+ # Receive a message from the Mailbox
42
+ def check(timeout = nil, &block)
43
+ # Get a message if it is available and process it immediately if possible:
44
+ if message = next_message(block)
45
+ return message
46
+ end
47
+
48
+ # ... otherwise, run the reactor once, either blocking or will return
49
+ # after the given timeout:
50
+ @reactor.run_once(timeout)
51
+
52
+ # No message was received:
53
+ return nil
54
+ end
55
+
56
+ # Obtain the next message from the mailbox that matches the given block
57
+ def next_message(block)
58
+ @mutex.lock
59
+ begin
60
+ super(&block)
61
+ ensure
62
+ @mutex.unlock rescue nil
63
+ end
64
+ end
65
+
66
+ # Cleanup any IO objects this Mailbox may be using
67
+ def shutdown
68
+ super do
69
+ @reactor.shutdown
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,4 +1,4 @@
1
- require 'thread'
1
+ require "thread"
2
2
 
3
3
  module Celluloid
4
4
  class MailboxDead < Celluloid::Error; end # you can't receive from the dead
@@ -52,37 +52,38 @@ module Celluloid
52
52
 
53
53
  @mutex.lock
54
54
  begin
55
- raise MailboxDead, "attempted to receive from a dead mailbox" if @dead
55
+ fail MailboxDead, "attempted to receive from a dead mailbox" if @dead
56
56
 
57
+ message = nil
57
58
  Timers::Wait.for(timeout) do |remaining|
58
59
  message = next_message(&block)
59
60
 
60
- break message if message
61
+ break if message
61
62
 
62
63
  @condition.wait(@mutex, remaining)
63
64
  end
64
65
  ensure
65
66
  @mutex.unlock rescue nil
66
67
  end
67
-
68
- return message
68
+
69
+ message
69
70
  end
70
71
 
71
72
  # Receive a letter from the mailbox. Guaranteed to return a message. If
72
- # timeout is exceeded, raise a TimeoutError.
73
+ # timeout is exceeded, raise a TaskTimeout.
73
74
  def receive(timeout = nil, &block)
75
+ message = nil
74
76
  Timers::Wait.for(timeout) do |remaining|
75
- if message = check(timeout, &block)
76
- return message
77
- end
77
+ message = check(timeout, &block)
78
+ break if message
78
79
  end
79
-
80
- raise TimeoutError.new("receive timeout exceeded")
80
+ return message if message
81
+ fail TaskTimeout.new("receive timeout exceeded")
81
82
  end
82
83
 
83
84
  # Shut down this mailbox and clean up its contents
84
85
  def shutdown
85
- raise MailboxDead, "mailbox already shutdown" if @dead
86
+ fail MailboxDead, "mailbox already shutdown" if @dead
86
87
 
87
88
  @mutex.lock
88
89
  begin
@@ -118,7 +119,7 @@ module Celluloid
118
119
 
119
120
  # Inspect the contents of the Mailbox
120
121
  def inspect
121
- "#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map { |m| m.inspect }.join(', ')}]>"
122
+ "#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map(&:inspect).join(', ')}]>"
122
123
  end
123
124
 
124
125
  # Number of messages in the Mailbox
@@ -146,7 +147,7 @@ module Celluloid
146
147
  end
147
148
 
148
149
  def dead_letter(message)
149
- Logger.debug "Discarded message (mailbox is dead): #{message}" if $CELLULOID_DEBUG
150
+ Internals::Logger.debug "Discarded message (mailbox is dead): #{message}" if $CELLULOID_DEBUG
150
151
  end
151
152
 
152
153
  def mailbox_full
@@ -0,0 +1,3 @@
1
+ $CELLULOID_BACKPORTED = false
2
+ $CELLULOID_MANAGED = true
3
+ require "celluloid/autostart"
@@ -0,0 +1,15 @@
1
+ module Celluloid
2
+ module Notices
3
+ class << self
4
+ @@notices = []
5
+
6
+ def backported
7
+ @@notices << [:info, "Celluloid #{Celluloid::VERSION} is running in BACKPORTED mode. [ http://git.io/vJf3J ]"]
8
+ end
9
+
10
+ def output
11
+ @@notices.each { |type, notice| Celluloid::Internals::Logger.send type, notice }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Celluloid
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"
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ module Celluloid::Proxy
2
+ # Looks up the actual class of instance, even if instance is a proxy.
3
+ def self.class_of(instance)
4
+ (class << instance; self; end).superclass
5
+ end
6
+ end
7
+
8
+ # Base class of Celluloid proxies
9
+ class Celluloid::Proxy::Abstract < BasicObject
10
+ # Needed for storing proxies in data structures
11
+ needed = [:object_id, :__id__, :hash, :eql?, :private_methods] - instance_methods
12
+ if needed.any?
13
+ include ::Kernel.dup.module_eval {
14
+ undef_method(*(instance_methods - needed))
15
+ self
16
+ }
17
+ # rubinius bug? These methods disappear when we include hacked kernel
18
+ define_method :==, ::BasicObject.instance_method(:==) unless instance_methods.include?(:==)
19
+ alias_method(:equal?, :==) unless instance_methods.include?(:equal?)
20
+ end
21
+
22
+ def __class__
23
+ @class ||= ::Celluloid::Proxy.class_of(self)
24
+ end
25
+ end
26
+
27
+ class Celluloid::Proxy::AbstractCall < Celluloid::Proxy::Abstract
28
+ attr_reader :mailbox
29
+
30
+ def initialize(mailbox, klass)
31
+ @mailbox = mailbox
32
+ @klass = klass
33
+ end
34
+
35
+ def eql?(other)
36
+ self.__class__.eql?(::Celluloid::Proxy.class_of(other)) and @mailbox.eql?(other.mailbox)
37
+ end
38
+
39
+ def hash
40
+ @mailbox.hash
41
+ end
42
+
43
+ def __klass__
44
+ @klass
45
+ end
46
+
47
+ def inspect
48
+ "#<#{self.__class__}(#{@klass})>"
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ # A proxy which controls the Actor lifecycle
2
+ class Celluloid::Proxy::Actor < Celluloid::Proxy::Abstract
3
+ attr_reader :thread, :mailbox
4
+
5
+ def initialize(mailbox, thread)
6
+ @mailbox = mailbox
7
+ @thread = thread
8
+ end
9
+
10
+ def inspect
11
+ # TODO: use a system event to fetch actor state: tasks?
12
+ "#<Celluloid::Proxy::Actor(#{@mailbox.address}) alive>"
13
+ rescue DeadActorError
14
+ "#<Celluloid::Proxy::Actor(#{@mailbox.address}) dead>"
15
+ end
16
+
17
+ def alive?
18
+ @mailbox.alive?
19
+ end
20
+
21
+ def dead?
22
+ !alive?
23
+ end
24
+
25
+ # Terminate the associated actor
26
+ def terminate
27
+ terminate!
28
+ ::Celluloid::Actor.join(self)
29
+ nil
30
+ end
31
+
32
+ # Terminate the associated actor asynchronously
33
+ def terminate!
34
+ ::Kernel.raise ::Celluloid::DeadActorError, "actor already terminated" unless alive?
35
+ @mailbox << ::Celluloid::TerminationRequest.new
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ # A proxy which sends asynchronous calls to an actor
2
+ class Celluloid::Proxy::Async < Celluloid::Proxy::AbstractCall
3
+ def method_missing(meth, *args, &block)
4
+ if @mailbox == ::Thread.current[:celluloid_mailbox]
5
+ args.unshift meth
6
+ meth = :__send__
7
+ end
8
+ if block_given?
9
+ # FIXME: nicer exception
10
+ fail "Cannot use blocks with async yet"
11
+ end
12
+ @mailbox << ::Celluloid::Call::Async.new(meth, args, block)
13
+ self
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ class Celluloid::Proxy::Block
2
+ attr_writer :execution
3
+ attr_reader :call, :block
4
+
5
+ def initialize(mailbox, call, block)
6
+ @mailbox = mailbox
7
+ @call = call
8
+ @block = block
9
+ @execution = :sender
10
+ end
11
+
12
+ def to_proc
13
+ if @execution == :sender
14
+ lambda do |*values|
15
+ if task = Thread.current[:celluloid_task]
16
+ @mailbox << ::Celluloid::Call::Block.new(self, ::Celluloid::Actor.current.mailbox, values)
17
+ # TODO: if respond fails, the Task will never be resumed
18
+ task.suspend(:invokeblock)
19
+ else
20
+ # FIXME: better exception
21
+ fail "No task to suspend"
22
+ end
23
+ end
24
+ else
25
+ @block
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,66 @@
1
+ # A proxy object returned from Celluloid::Actor.new/new_link which converts
2
+ # the normal Ruby method protocol into an inter-actor message protocol
3
+ class Celluloid::Proxy::Cell < Celluloid::Proxy::Sync
4
+ def initialize(mailbox, actor_proxy, klass)
5
+ super(mailbox, klass)
6
+ @actor_proxy = actor_proxy
7
+ @async_proxy = ::Celluloid::Proxy::Async.new(mailbox, klass)
8
+ @future_proxy = ::Celluloid::Proxy::Future.new(mailbox, klass)
9
+ end
10
+
11
+ def _send_(meth, *args, &block)
12
+ method_missing :__send__, meth, *args, &block
13
+ end
14
+
15
+ def inspect
16
+ method_missing :inspect
17
+ rescue ::Celluloid::DeadActorError
18
+ "#<::Celluloid::Proxy::Cell(#{@klass}) dead>"
19
+ end
20
+
21
+ def method(name)
22
+ ::Celluloid::Internals::Method.new(self, name)
23
+ end
24
+
25
+ alias_method :sync, :method_missing
26
+
27
+ # Obtain an async proxy or explicitly invoke a named async method
28
+ def async(method_name = nil, *args, &block)
29
+ if method_name
30
+ @async_proxy.method_missing method_name, *args, &block
31
+ else
32
+ @async_proxy
33
+ end
34
+ end
35
+
36
+ # Obtain a future proxy or explicitly invoke a named future method
37
+ def future(method_name = nil, *args, &block)
38
+ if method_name
39
+ @future_proxy.method_missing method_name, *args, &block
40
+ else
41
+ @future_proxy
42
+ end
43
+ end
44
+
45
+ def alive?
46
+ @actor_proxy.alive?
47
+ end
48
+
49
+ def dead?
50
+ @actor_proxy.dead?
51
+ end
52
+
53
+ def thread
54
+ @actor_proxy.thread
55
+ end
56
+
57
+ # Terminate the associated actor
58
+ def terminate
59
+ @actor_proxy.terminate
60
+ end
61
+
62
+ # Terminate the associated actor asynchronously
63
+ def terminate!
64
+ @actor_proxy.terminate!
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ # A proxy which creates future calls to an actor
2
+ class Celluloid::Proxy::Future < Celluloid::Proxy::AbstractCall
3
+ def method_missing(meth, *args, &block)
4
+ unless @mailbox.alive?
5
+ fail ::Celluloid::DeadActorError, "attempted to call a dead actor: #{meth}"
6
+ end
7
+
8
+ if block_given?
9
+ # FIXME: nicer exception
10
+ fail "Cannot use blocks with futures yet"
11
+ end
12
+
13
+ future = ::Celluloid::Future.new
14
+ call = ::Celluloid::Call::Sync.new(future, meth, args, block)
15
+
16
+ @mailbox << call
17
+
18
+ future
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # A proxy which sends synchronous calls to an actor
2
+ class Celluloid::Proxy::Sync < Celluloid::Proxy::AbstractCall
3
+ def respond_to?(meth, include_private = false)
4
+ __class__.instance_methods.include?(meth) || method_missing(:respond_to?, meth, include_private)
5
+ end
6
+
7
+ def method_missing(meth, *args, &block)
8
+ unless @mailbox.alive?
9
+ fail ::Celluloid::DeadActorError, "attempted to call a dead actor: #{meth}"
10
+ end
11
+
12
+ if @mailbox == ::Thread.current[:celluloid_mailbox]
13
+ args.unshift meth
14
+ meth = :__send__
15
+ # actor = Thread.current[:celluloid_actor]
16
+ # actor = actor.behavior.subject.bare_object
17
+ # return actor.__send__(*args, &block)
18
+ end
19
+
20
+ call = ::Celluloid::Call::Sync.new(::Celluloid.mailbox, meth, args, block)
21
+ @mailbox << call
22
+ call.value
23
+ end
24
+ end
@@ -1,13 +1,71 @@
1
- require 'celluloid/rspec/example_actor_class'
2
- require 'celluloid/rspec/actor_examples'
3
- require 'celluloid/rspec/mailbox_examples'
4
- require 'celluloid/rspec/task_examples'
5
-
6
- module Celluloid
7
- # Timer accuracy enforced by the tests (50ms)
8
- TIMER_QUANTUM = 0.05
1
+ require "dotenv"
2
+ require "nenv"
3
+
4
+ require "celluloid/test"
5
+
6
+ # To help produce better bug reports in Rubinius
7
+ if RUBY_ENGINE == "rbx"
8
+ # $DEBUG = true # would be nice if this didn't fail ... :(
9
+ require "rspec/matchers"
10
+ require "rspec/matchers/built_in/be"
11
+ end
12
+
13
+ require "rspec/retry"
14
+
15
+ module Specs
16
+
17
+ CHECK_LOOSE_THREADS = !Nenv.ci? unless defined? CHECK_LOOSE_THREADS
18
+ ALLOW_RETRIES = 3 unless defined? ALLOW_RETRIES
19
+
20
+ INCLUDE_SUPPORT = [
21
+ "env",
22
+ "logging",
23
+ "sleep_and_wait",
24
+ "reset_class_variables",
25
+ "crash_checking",
26
+ "loose_threads",
27
+ "stubbing",
28
+ "coverage",
29
+ "includer",
30
+ "configure_rspec"
31
+ ]
32
+
33
+ INCLUDE_PATHS = [
34
+ "./spec/support/*.rb",
35
+ "./spec/support/examples/*.rb",
36
+ "./spec/shared/*.rb"
37
+ ]
38
+
39
+ MAX_EXECUTION = 13
40
+ MAX_ATTEMPTS = 20
41
+
42
+ TIMER_QUANTUM = 0.05 # Timer accuracy enforced by the tests (50ms)
43
+
44
+ BACKTRACE_OMITTED = [
45
+ "rspec-expectations",
46
+ "rspec-core",
47
+ "rspec-mocks",
48
+ "rspec-retry",
49
+ "rubysl-thread",
50
+ "rubysl-timeout"
51
+ ]
9
52
  end
10
53
 
11
54
  $CELLULOID_DEBUG = true
12
55
 
13
- require 'celluloid/test'
56
+ # Require but disable, so it has to be explicitly enabled in tests
57
+ require "celluloid/probe"
58
+ $CELLULOID_MONITORING = false
59
+
60
+ Celluloid.shutdown_timeout = 1
61
+
62
+ # Load shared examples and test support code for other gems to use.
63
+
64
+ Specs::INCLUDE_SUPPORT.each { |f|
65
+ require "#{File.expand_path('../../../spec/support', __FILE__)}/#{f}.rb"
66
+ }
67
+
68
+ Specs.reset_probe(nil)
69
+
70
+ Dir["#{File.expand_path('../../../spec/support/examples', __FILE__)}/*.rb"].map { |f| require f }
71
+ Dir["#{File.expand_path('../../../spec/shared', __FILE__)}/*.rb"].map { |f| require f }