celluloid 0.16.0 → 0.17.0

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +333 -0
  3. data/README.md +1 -1
  4. data/culture/CODE_OF_CONDUCT.md +28 -0
  5. data/culture/Gemfile +9 -0
  6. data/culture/README.md +22 -0
  7. data/culture/Rakefile +5 -0
  8. data/culture/SYNC.md +70 -0
  9. data/culture/celluloid-culture.gemspec +18 -0
  10. data/culture/gems/README.md +39 -0
  11. data/culture/gems/dependencies.yml +78 -0
  12. data/culture/gems/loader.rb +101 -0
  13. data/culture/rubocop/README.md +38 -0
  14. data/culture/rubocop/lint.yml +8 -0
  15. data/culture/rubocop/metrics.yml +15 -0
  16. data/culture/rubocop/rubocop.yml +4 -0
  17. data/culture/rubocop/style.yml +48 -0
  18. data/culture/spec/gems_spec.rb +2 -0
  19. data/culture/spec/spec_helper.rb +0 -0
  20. data/culture/spec/sync_spec.rb +2 -0
  21. data/culture/sync.rb +56 -0
  22. data/culture/tasks/rspec.rake +5 -0
  23. data/culture/tasks/rubocop.rake +2 -0
  24. data/examples/basic_usage.rb +49 -0
  25. data/examples/futures.rb +38 -0
  26. data/examples/ring.rb +61 -0
  27. data/examples/simple_pmap.rb +14 -0
  28. data/examples/timers.rb +72 -0
  29. data/lib/celluloid.rb +142 -127
  30. data/lib/celluloid/actor.rb +47 -41
  31. data/lib/celluloid/actor_system.rb +75 -22
  32. data/lib/celluloid/autostart.rb +1 -1
  33. data/lib/celluloid/backported.rb +2 -0
  34. data/lib/celluloid/call/async.rb +16 -0
  35. data/lib/celluloid/call/block.rb +22 -0
  36. data/lib/celluloid/call/sync.rb +70 -0
  37. data/lib/celluloid/calls.rb +25 -114
  38. data/lib/celluloid/cell.rb +32 -20
  39. data/lib/celluloid/condition.rb +3 -3
  40. data/lib/celluloid/core_ext.rb +1 -1
  41. data/lib/celluloid/current.rb +2 -0
  42. data/lib/celluloid/deprecate.rb +18 -0
  43. data/lib/celluloid/exceptions.rb +1 -1
  44. data/lib/celluloid/fiber.rb +3 -3
  45. data/lib/celluloid/future.rb +7 -6
  46. data/lib/celluloid/group.rb +65 -0
  47. data/lib/celluloid/group/manager.rb +27 -0
  48. data/lib/celluloid/group/pool.rb +125 -0
  49. data/lib/celluloid/group/spawner.rb +71 -0
  50. data/lib/celluloid/logging.rb +5 -5
  51. data/lib/celluloid/mailbox.rb +14 -13
  52. data/lib/celluloid/mailbox/evented.rb +76 -0
  53. data/lib/celluloid/notices.rb +15 -0
  54. data/lib/celluloid/proxies.rb +12 -0
  55. data/lib/celluloid/proxy/abstract.rb +24 -0
  56. data/lib/celluloid/proxy/actor.rb +46 -0
  57. data/lib/celluloid/proxy/async.rb +36 -0
  58. data/lib/celluloid/proxy/block.rb +31 -0
  59. data/lib/celluloid/proxy/cell.rb +76 -0
  60. data/lib/celluloid/proxy/future.rb +40 -0
  61. data/lib/celluloid/proxy/sync.rb +44 -0
  62. data/lib/celluloid/rspec.rb +9 -10
  63. data/lib/celluloid/system_events.rb +16 -15
  64. data/lib/celluloid/{tasks.rb → task.rb} +21 -21
  65. data/lib/celluloid/task/fibered.rb +45 -0
  66. data/lib/celluloid/task/threaded.rb +59 -0
  67. data/lib/celluloid/test.rb +1 -1
  68. data/lib/celluloid/thread.rb +6 -1
  69. data/lib/celluloid/version.rb +3 -0
  70. data/spec/celluloid/actor_spec.rb +2 -2
  71. data/spec/celluloid/actor_system_spec.rb +35 -21
  72. data/spec/celluloid/block_spec.rb +3 -5
  73. data/spec/celluloid/calls_spec.rb +33 -11
  74. data/spec/celluloid/condition_spec.rb +16 -13
  75. data/spec/celluloid/evented_mailbox_spec.rb +1 -31
  76. data/spec/celluloid/future_spec.rb +13 -10
  77. data/spec/celluloid/group/elastic_spec.rb +0 -0
  78. data/spec/celluloid/group/manager_spec.rb +0 -0
  79. data/spec/celluloid/group/pool_spec.rb +8 -0
  80. data/spec/celluloid/group/spawner_spec.rb +8 -0
  81. data/spec/celluloid/mailbox/evented_spec.rb +27 -0
  82. data/spec/celluloid/mailbox_spec.rb +1 -3
  83. data/spec/celluloid/misc/leak_spec.rb +73 -0
  84. data/spec/celluloid/task/fibered_spec.rb +5 -0
  85. data/spec/celluloid/task/threaded_spec.rb +5 -0
  86. data/spec/celluloid/timer_spec.rb +14 -16
  87. data/spec/deprecate/actor_system_spec.rb +72 -0
  88. data/spec/deprecate/block_spec.rb +52 -0
  89. data/spec/deprecate/calls_spec.rb +57 -0
  90. data/spec/deprecate/evented_mailbox_spec.rb +34 -0
  91. data/spec/deprecate/future_spec.rb +32 -0
  92. data/spec/deprecate/internal_pool_spec.rb +4 -0
  93. data/spec/shared/actor_examples.rb +1237 -0
  94. data/spec/shared/group_examples.rb +121 -0
  95. data/{lib/celluloid/rspec → spec/shared}/mailbox_examples.rb +20 -17
  96. data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
  97. data/spec/spec_helper.rb +72 -16
  98. data/spec/support/coverage.rb +4 -0
  99. data/spec/support/crash_checking.rb +68 -0
  100. data/spec/support/debugging.rb +31 -0
  101. data/spec/support/env.rb +16 -0
  102. data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
  103. data/spec/support/examples/evented_mailbox_class.rb +27 -0
  104. data/spec/support/includer.rb +9 -0
  105. data/spec/support/logging.rb +63 -0
  106. data/spec/support/loose_threads.rb +65 -0
  107. data/spec/support/reset_class_variables.rb +27 -0
  108. data/spec/support/sleep_and_wait.rb +14 -0
  109. data/spec/support/split_logs.rb +1 -0
  110. data/spec/support/stubbing.rb +14 -0
  111. metadata +255 -95
  112. data/lib/celluloid/call_chain.rb +0 -13
  113. data/lib/celluloid/cpu_counter.rb +0 -34
  114. data/lib/celluloid/evented_mailbox.rb +0 -73
  115. data/lib/celluloid/fsm.rb +0 -186
  116. data/lib/celluloid/handlers.rb +0 -41
  117. data/lib/celluloid/internal_pool.rb +0 -159
  118. data/lib/celluloid/legacy.rb +0 -9
  119. data/lib/celluloid/links.rb +0 -36
  120. data/lib/celluloid/logger.rb +0 -93
  121. data/lib/celluloid/logging/incident.rb +0 -21
  122. data/lib/celluloid/logging/incident_logger.rb +0 -129
  123. data/lib/celluloid/logging/incident_reporter.rb +0 -48
  124. data/lib/celluloid/logging/log_event.rb +0 -20
  125. data/lib/celluloid/logging/ring_buffer.rb +0 -65
  126. data/lib/celluloid/method.rb +0 -32
  127. data/lib/celluloid/notifications.rb +0 -83
  128. data/lib/celluloid/pool_manager.rb +0 -146
  129. data/lib/celluloid/probe.rb +0 -73
  130. data/lib/celluloid/properties.rb +0 -24
  131. data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
  132. data/lib/celluloid/proxies/actor_proxy.rb +0 -38
  133. data/lib/celluloid/proxies/async_proxy.rb +0 -31
  134. data/lib/celluloid/proxies/block_proxy.rb +0 -29
  135. data/lib/celluloid/proxies/cell_proxy.rb +0 -68
  136. data/lib/celluloid/proxies/future_proxy.rb +0 -35
  137. data/lib/celluloid/proxies/sync_proxy.rb +0 -36
  138. data/lib/celluloid/receivers.rb +0 -63
  139. data/lib/celluloid/registry.rb +0 -57
  140. data/lib/celluloid/responses.rb +0 -44
  141. data/lib/celluloid/rspec/actor_examples.rb +0 -1054
  142. data/lib/celluloid/signals.rb +0 -23
  143. data/lib/celluloid/stack_dump.rb +0 -133
  144. data/lib/celluloid/supervision_group.rb +0 -169
  145. data/lib/celluloid/supervisor.rb +0 -22
  146. data/lib/celluloid/task_set.rb +0 -49
  147. data/lib/celluloid/tasks/task_fiber.rb +0 -43
  148. data/lib/celluloid/tasks/task_thread.rb +0 -53
  149. data/lib/celluloid/thread_handle.rb +0 -50
  150. data/lib/celluloid/uuid.rb +0 -38
  151. data/spec/celluloid/cpu_counter_spec.rb +0 -82
  152. data/spec/celluloid/fsm_spec.rb +0 -107
  153. data/spec/celluloid/internal_pool_spec.rb +0 -52
  154. data/spec/celluloid/links_spec.rb +0 -45
  155. data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
  156. data/spec/celluloid/notifications_spec.rb +0 -120
  157. data/spec/celluloid/pool_spec.rb +0 -92
  158. data/spec/celluloid/probe_spec.rb +0 -121
  159. data/spec/celluloid/properties_spec.rb +0 -42
  160. data/spec/celluloid/registry_spec.rb +0 -64
  161. data/spec/celluloid/stack_dump_spec.rb +0 -64
  162. data/spec/celluloid/supervision_group_spec.rb +0 -65
  163. data/spec/celluloid/supervisor_spec.rb +0 -103
  164. data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
  165. data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
  166. data/spec/celluloid/thread_handle_spec.rb +0 -26
  167. data/spec/celluloid/uuid_spec.rb +0 -11
@@ -1,83 +0,0 @@
1
- module Celluloid
2
- module Notifications
3
- def self.notifier
4
- Actor[:notifications_fanout] or raise DeadActorError, "notifications fanout actor not running"
5
- end
6
-
7
- def publish(pattern, *args)
8
- Celluloid::Notifications.notifier.publish(pattern, *args)
9
- end
10
-
11
- def subscribe(pattern, method)
12
- Celluloid::Notifications.notifier.subscribe(Actor.current, pattern, method)
13
- end
14
-
15
- def unsubscribe(*args)
16
- Celluloid::Notifications.notifier.unsubscribe(*args)
17
- end
18
-
19
- class Fanout
20
- include Celluloid
21
- trap_exit :prune
22
-
23
- def initialize
24
- @subscribers = []
25
- @listeners_for = {}
26
- end
27
-
28
- def subscribe(actor, pattern, method)
29
- subscriber = Subscriber.new(actor, pattern, method).tap do |s|
30
- @subscribers << s
31
- end
32
- link actor
33
- @listeners_for.clear
34
- subscriber
35
- end
36
-
37
- def unsubscribe(subscriber)
38
- @subscribers.reject! { |s| s.matches?(subscriber) }
39
- @listeners_for.clear
40
- end
41
-
42
- def publish(pattern, *args)
43
- listeners_for(pattern).each { |s| s.publish(pattern, *args) }
44
- end
45
-
46
- def listeners_for(pattern)
47
- @listeners_for[pattern] ||= @subscribers.select { |s| s.subscribed_to?(pattern) }
48
- end
49
-
50
- def listening?(pattern)
51
- listeners_for(pattern).any?
52
- end
53
-
54
- def prune(actor, reason=nil)
55
- @subscribers.reject! { |s| s.actor == actor }
56
- @listeners_for.clear
57
- end
58
- end
59
-
60
- class Subscriber
61
- attr_accessor :actor, :pattern, :method
62
-
63
- def initialize(actor, pattern, method)
64
- @actor = actor
65
- @pattern = pattern
66
- @method = method
67
- end
68
-
69
- def publish(pattern, *args)
70
- actor.async method, pattern, *args
71
- end
72
-
73
- def subscribed_to?(pattern)
74
- !pattern || @pattern === pattern.to_s
75
- end
76
-
77
- def matches?(subscriber_or_pattern)
78
- self === subscriber_or_pattern ||
79
- @pattern && @pattern === subscriber_or_pattern
80
- end
81
- end
82
- end
83
- end
@@ -1,146 +0,0 @@
1
- require 'set'
2
-
3
- module Celluloid
4
- # Manages a fixed-size pool of workers
5
- # Delegates work (i.e. methods) and supervises workers
6
- # Don't use this class directly. Instead use MyKlass.pool
7
- class PoolManager
8
- include Celluloid
9
- trap_exit :__crash_handler__
10
- finalizer :__shutdown__
11
-
12
- def initialize(worker_class, options = {})
13
- @size = options[:size] || [Celluloid.cores || 2, 2].max
14
- raise ArgumentError, "minimum pool size is 2" if @size < 2
15
-
16
- @worker_class = worker_class
17
- @args = options[:args] ? Array(options[:args]) : []
18
-
19
- @idle = @size.times.map { worker_class.new_link(*@args) }
20
-
21
- # FIXME: Another data structure (e.g. Set) would be more appropriate
22
- # here except it causes MRI to crash :o
23
- @busy = []
24
- end
25
-
26
- def __shutdown__
27
- terminators = (@idle + @busy).map do |actor|
28
- begin
29
- actor.future(:terminate)
30
- rescue DeadActorError
31
- end
32
- end
33
-
34
- terminators.compact.each { |terminator| terminator.value rescue nil }
35
- end
36
-
37
- def _send_(method, *args, &block)
38
- worker = __provision_worker__
39
-
40
- begin
41
- worker._send_ method, *args, &block
42
- rescue DeadActorError # if we get a dead actor out of the pool
43
- wait :respawn_complete
44
- worker = __provision_worker__
45
- retry
46
- rescue Exception => ex
47
- abort ex
48
- ensure
49
- if worker.alive?
50
- @idle << worker
51
- @busy.delete worker
52
- end
53
- end
54
- end
55
-
56
- def name
57
- _send_ @mailbox, :name
58
- end
59
-
60
- def is_a?(klass)
61
- _send_ :is_a?, klass
62
- end
63
-
64
- def kind_of?(klass)
65
- _send_ :kind_of?, klass
66
- end
67
-
68
- def methods(include_ancestors = true)
69
- _send_ :methods, include_ancestors
70
- end
71
-
72
- def to_s
73
- _send_ :to_s
74
- end
75
-
76
- def inspect
77
- _send_ :inspect
78
- end
79
-
80
- def size
81
- @size
82
- end
83
-
84
- def size=(new_size)
85
- new_size = [0, new_size].max
86
-
87
- if new_size > size
88
- delta = new_size - size
89
- delta.times { @idle << @worker_class.new_link(*@args) }
90
- else
91
- (size - new_size).times do
92
- worker = __provision_worker__
93
- unlink worker
94
- @busy.delete worker
95
- worker.terminate
96
- end
97
- end
98
- @size = new_size
99
- end
100
-
101
- def busy_size
102
- @busy.length
103
- end
104
-
105
- def idle_size
106
- @idle.length
107
- end
108
-
109
- # Provision a new worker
110
- def __provision_worker__
111
- Task.current.guard_warnings = true
112
- while @idle.empty?
113
- # Wait for responses from one of the busy workers
114
- response = exclusive { receive { |msg| msg.is_a?(Response) } }
115
- Thread.current[:celluloid_actor].handle_message(response)
116
- end
117
-
118
- worker = @idle.shift
119
- @busy << worker
120
-
121
- worker
122
- end
123
-
124
- # Spawn a new worker for every crashed one
125
- def __crash_handler__(actor, reason)
126
- @busy.delete actor
127
- @idle.delete actor
128
- return unless reason
129
-
130
- @idle << @worker_class.new_link(*@args)
131
- signal :respawn_complete
132
- end
133
-
134
- def respond_to?(method, include_private = false)
135
- super || @worker_class.instance_methods.include?(method.to_sym)
136
- end
137
-
138
- def method_missing(method, *args, &block)
139
- if respond_to?(method)
140
- _send_ method, *args, &block
141
- else
142
- super
143
- end
144
- end
145
- end
146
- end
@@ -1,73 +0,0 @@
1
- require 'celluloid'
2
-
3
- $CELLULOID_MONITORING = true
4
-
5
- module Celluloid
6
- class Probe
7
- include Celluloid
8
- include Celluloid::Notifications
9
-
10
- NOTIFICATIONS_TOPIC_BASE = 'celluloid.events.%s'
11
- INITIAL_EVENTS = Queue.new
12
-
13
- class << self
14
- def run
15
- # spawn the actor if not found
16
- supervise_as(:probe_actor) unless Actor[:probe_actor] && Actor[:probe_actor].alive?
17
- end
18
-
19
- def actor_created(actor)
20
- trigger_event(:actor_created, actor)
21
- end
22
-
23
- def actor_named(actor)
24
- trigger_event(:actor_named, actor)
25
- end
26
-
27
- def actor_died(actor)
28
- trigger_event(:actor_died, actor)
29
- end
30
-
31
- def actors_linked(a, b)
32
- a = find_actor(a)
33
- b = find_actor(b)
34
- trigger_event(:actors_linked, a, b)
35
- end
36
-
37
- private
38
-
39
- def trigger_event(name, *args)
40
- return unless $CELLULOID_MONITORING
41
- probe_actor = Actor[:probe_actor]
42
- if probe_actor
43
- probe_actor.async.dispatch_event(name, args)
44
- else
45
- INITIAL_EVENTS << [name, args]
46
- end
47
- end
48
-
49
- def find_actor(obj)
50
- if obj.__send__(:class) == Actor
51
- obj
52
- elsif owner = obj.instance_variable_get(OWNER_IVAR)
53
- owner
54
- end
55
- end
56
- end
57
-
58
- def initialize
59
- async.first_run
60
- end
61
-
62
- def first_run
63
- until INITIAL_EVENTS.size == 0
64
- event = INITIAL_EVENTS.pop
65
- dispatch_event(*event)
66
- end
67
- end
68
-
69
- def dispatch_event(cmd, args)
70
- publish(NOTIFICATIONS_TOPIC_BASE % cmd, args)
71
- end
72
- end
73
- end
@@ -1,24 +0,0 @@
1
- module Celluloid
2
- # Properties define inheritable attributes of classes, somewhat similar to
3
- # Rails cattr_*/mattr_* or class_attribute
4
- module Properties
5
- def property(name, opts = {})
6
- default = opts.fetch(:default, nil)
7
- multi = opts.fetch(:multi, false)
8
- ivar_name = "@#{name}".to_sym
9
-
10
- ancestors.first.send(:define_singleton_method, name) do |value = nil, *extra|
11
- if value
12
- value = value ? [value, *send(name), *extra].uniq : [] if multi
13
- instance_variable_set(ivar_name, value)
14
- elsif instance_variables.include?(ivar_name)
15
- instance_variable_get(ivar_name)
16
- elsif superclass.respond_to? name
17
- superclass.send(name)
18
- else
19
- default
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,20 +0,0 @@
1
- module Celluloid
2
- # Base class of all Celluloid proxies
3
- class AbstractProxy < BasicObject
4
- # Used for reflecting on proxy objects themselves
5
- def __class__; AbstractProxy; end
6
-
7
- # Needed for storing proxies in data structures
8
- needed = [:object_id, :__id__, :hash] - instance_methods
9
- if needed.any?
10
- include ::Kernel.dup.module_eval {
11
- undef_method(*(instance_methods - needed))
12
- self
13
- }
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?)
18
- end
19
- end
20
- end
@@ -1,38 +0,0 @@
1
- module Celluloid
2
- # A proxy which controls the Actor lifecycle
3
- class ActorProxy < AbstractProxy
4
- attr_reader :thread, :mailbox
5
-
6
- # Used for reflecting on proxy objects themselves
7
- def __class__; ActorProxy; end
8
-
9
- def initialize(thread, mailbox)
10
- @thread = thread
11
- @mailbox = mailbox
12
- end
13
-
14
- def inspect
15
- # TODO: use a system event to fetch actor state: tasks?
16
- "#<Celluloid::ActorProxy(#{@mailbox.address}) alive>"
17
- rescue DeadActorError
18
- "#<Celluloid::ActorProxy(#{@mailbox.address}) dead>"
19
- end
20
-
21
- def alive?
22
- @mailbox.alive?
23
- end
24
-
25
- # Terminate the associated actor
26
- def terminate
27
- terminate!
28
- Actor.join(self)
29
- nil
30
- end
31
-
32
- # Terminate the associated actor asynchronously
33
- def terminate!
34
- ::Kernel.raise DeadActorError, "actor already terminated" unless alive?
35
- @mailbox << TerminationRequest.new
36
- end
37
- end
38
- end
@@ -1,31 +0,0 @@
1
- module Celluloid
2
- # A proxy which sends asynchronous calls to an actor
3
- class AsyncProxy < AbstractProxy
4
- attr_reader :mailbox
5
-
6
- # Used for reflecting on proxy objects themselves
7
- def __class__; AsyncProxy; end
8
-
9
- def initialize(mailbox, klass)
10
- @mailbox, @klass = mailbox, klass
11
- end
12
-
13
- def inspect
14
- "#<Celluloid::AsyncProxy(#{@klass})>"
15
- end
16
-
17
- def method_missing(meth, *args, &block)
18
- if @mailbox == ::Thread.current[:celluloid_mailbox]
19
- args.unshift meth
20
- meth = :__send__
21
- end
22
-
23
- if block_given?
24
- # FIXME: nicer exception
25
- raise "Cannot use blocks with async yet"
26
- end
27
-
28
- @mailbox << AsyncCall.new(meth, args, block)
29
- end
30
- end
31
- end
@@ -1,29 +0,0 @@
1
- module Celluloid
2
- class BlockProxy
3
- def initialize(call, mailbox, block)
4
- @call = call
5
- @mailbox = mailbox
6
- @block = block
7
- @execution = :sender
8
- end
9
- attr_writer :execution
10
- attr_reader :call, :block
11
-
12
- def to_proc
13
- if @execution == :sender
14
- lambda do |*values|
15
- if task = Thread.current[:celluloid_task]
16
- @mailbox << BlockCall.new(self, 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
- raise "No task to suspend"
22
- end
23
- end
24
- else
25
- @block
26
- end
27
- end
28
- end
29
- end