celluloid 0.17.3 → 0.18.0

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 (171) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +300 -73
  3. data/CONDUCT.md +13 -0
  4. data/CONTRIBUTING.md +39 -0
  5. data/README.md +54 -150
  6. data/REFACTOR.md +1 -0
  7. data/architecture.md +120 -0
  8. data/examples/basic_usage.rb +1 -1
  9. data/examples/configurations.rb +78 -0
  10. data/examples/futures.rb +1 -1
  11. data/examples/ring.rb +5 -4
  12. data/examples/simple_pmap.rb +1 -1
  13. data/examples/stack.rb +2 -2
  14. data/examples/supervisors_and_registry.rb +82 -0
  15. data/examples/timers.rb +2 -2
  16. data/lib/celluloid.rb +74 -64
  17. data/lib/celluloid/actor.rb +27 -17
  18. data/lib/celluloid/actor/system.rb +13 -29
  19. data/lib/celluloid/autostart.rb +6 -1
  20. data/lib/celluloid/call/async.rb +2 -0
  21. data/lib/celluloid/call/sync.rb +10 -3
  22. data/lib/celluloid/calls.rb +13 -12
  23. data/lib/celluloid/cell.rb +5 -9
  24. data/lib/celluloid/condition.rb +3 -3
  25. data/lib/celluloid/core_ext.rb +0 -2
  26. data/lib/celluloid/debug.rb +3 -0
  27. data/lib/celluloid/exceptions.rb +2 -2
  28. data/lib/celluloid/future.rb +8 -10
  29. data/lib/celluloid/group.rb +16 -6
  30. data/lib/celluloid/group/pool.rb +1 -3
  31. data/lib/celluloid/group/spawner.rb +2 -6
  32. data/lib/celluloid/internals/call_chain.rb +15 -0
  33. data/lib/celluloid/internals/cpu_counter.rb +62 -0
  34. data/lib/celluloid/internals/handlers.rb +42 -0
  35. data/lib/celluloid/internals/links.rb +38 -0
  36. data/lib/celluloid/internals/logger.rb +104 -0
  37. data/lib/celluloid/internals/method.rb +34 -0
  38. data/lib/celluloid/internals/properties.rb +32 -0
  39. data/lib/celluloid/internals/receivers.rb +64 -0
  40. data/lib/celluloid/internals/registry.rb +102 -0
  41. data/lib/celluloid/internals/responses.rb +46 -0
  42. data/lib/celluloid/internals/signals.rb +24 -0
  43. data/lib/celluloid/internals/stack.rb +74 -0
  44. data/lib/celluloid/internals/stack/dump.rb +12 -0
  45. data/lib/celluloid/internals/stack/states.rb +72 -0
  46. data/lib/celluloid/internals/stack/summary.rb +12 -0
  47. data/lib/celluloid/internals/task_set.rb +51 -0
  48. data/lib/celluloid/internals/thread_handle.rb +52 -0
  49. data/lib/celluloid/internals/uuid.rb +40 -0
  50. data/lib/celluloid/logging/incident.rb +21 -0
  51. data/lib/celluloid/logging/incident_logger.rb +147 -0
  52. data/lib/celluloid/logging/incident_reporter.rb +49 -0
  53. data/lib/celluloid/logging/log_event.rb +20 -0
  54. data/lib/celluloid/logging/ring_buffer.rb +64 -0
  55. data/lib/celluloid/mailbox.rb +22 -9
  56. data/lib/celluloid/mailbox/evented.rb +13 -5
  57. data/lib/celluloid/notifications.rb +95 -0
  58. data/lib/celluloid/pool.rb +6 -0
  59. data/lib/celluloid/probe.rb +81 -0
  60. data/lib/celluloid/proxy/abstract.rb +9 -9
  61. data/lib/celluloid/proxy/async.rb +1 -1
  62. data/lib/celluloid/proxy/block.rb +2 -2
  63. data/lib/celluloid/proxy/cell.rb +1 -1
  64. data/lib/celluloid/proxy/future.rb +2 -4
  65. data/lib/celluloid/proxy/sync.rb +1 -3
  66. data/lib/celluloid/rspec.rb +22 -33
  67. data/lib/celluloid/supervision.rb +17 -0
  68. data/lib/celluloid/supervision/configuration.rb +169 -0
  69. data/lib/celluloid/supervision/configuration/injections.rb +8 -0
  70. data/lib/celluloid/supervision/configuration/instance.rb +113 -0
  71. data/lib/celluloid/supervision/constants.rb +123 -0
  72. data/lib/celluloid/supervision/container.rb +144 -0
  73. data/lib/celluloid/supervision/container/behavior.rb +89 -0
  74. data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
  75. data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
  76. data/lib/celluloid/supervision/container/injections.rb +8 -0
  77. data/lib/celluloid/supervision/container/instance.rb +116 -0
  78. data/lib/celluloid/supervision/container/pool.rb +210 -0
  79. data/lib/celluloid/supervision/service.rb +27 -0
  80. data/lib/celluloid/supervision/supervise.rb +34 -0
  81. data/lib/celluloid/supervision/validation.rb +40 -0
  82. data/lib/celluloid/supervision/version.rb +5 -0
  83. data/lib/celluloid/system_events.rb +11 -6
  84. data/lib/celluloid/task.rb +25 -12
  85. data/lib/celluloid/task/fibered.rb +6 -2
  86. data/lib/celluloid/task/threaded.rb +3 -3
  87. data/lib/celluloid/test.rb +5 -2
  88. data/lib/celluloid/thread.rb +0 -2
  89. data/lib/celluloid/version.rb +1 -1
  90. data/spec/celluloid/block_spec.rb +29 -32
  91. data/spec/celluloid/calls_spec.rb +5 -15
  92. data/spec/celluloid/future_spec.rb +7 -1
  93. data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
  94. data/spec/celluloid/internals/links_spec.rb +43 -0
  95. data/spec/celluloid/internals/properties_spec.rb +40 -0
  96. data/spec/celluloid/internals/registry_spec.rb +62 -0
  97. data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
  98. data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
  99. data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
  100. data/spec/celluloid/internals/uuid_spec.rb +9 -0
  101. data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
  102. data/spec/celluloid/mailbox/evented_spec.rb +11 -22
  103. data/spec/celluloid/misc/leak_spec.rb +3 -4
  104. data/spec/celluloid/notifications_spec.rb +140 -0
  105. data/spec/celluloid/probe_spec.rb +102 -0
  106. data/spec/celluloid/proxy_spec.rb +30 -30
  107. data/spec/celluloid/supervision/behavior_spec.rb +74 -0
  108. data/spec/celluloid/supervision/configuration_spec.rb +181 -0
  109. data/spec/celluloid/supervision/container_spec.rb +72 -0
  110. data/spec/celluloid/supervision/instance_spec.rb +13 -0
  111. data/spec/celluloid/supervision/root_spec.rb +28 -0
  112. data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
  113. data/spec/celluloid/task/fibered_spec.rb +1 -3
  114. data/spec/celluloid/task/threaded_spec.rb +1 -3
  115. data/spec/shared/actor_examples.rb +58 -33
  116. data/spec/shared/group_examples.rb +2 -2
  117. data/spec/shared/mailbox_examples.rb +1 -1
  118. data/spec/shared/stack_examples.rb +87 -0
  119. data/spec/shared/task_examples.rb +2 -3
  120. data/spec/spec_helper.rb +2 -4
  121. data/spec/support/configure_rspec.rb +2 -3
  122. data/spec/support/coverage.rb +2 -4
  123. data/spec/support/crash_checking.rb +2 -2
  124. data/spec/support/examples/actor_class.rb +3 -8
  125. data/spec/support/examples/call_class.rb +2 -2
  126. data/spec/support/examples/container_class.rb +35 -0
  127. data/spec/support/examples/evented_mailbox_class.rb +1 -2
  128. data/spec/support/examples/stack_classes.rb +58 -0
  129. data/spec/support/examples/stack_methods.rb +23 -0
  130. data/spec/support/examples/subordinate_class.rb +19 -0
  131. data/spec/support/logging.rb +3 -34
  132. data/spec/support/loose_threads.rb +3 -16
  133. data/spec/support/reset_class_variables.rb +5 -1
  134. data/spec/support/stubbing.rb +1 -1
  135. metadata +91 -290
  136. data/culture/CONDUCT.md +0 -28
  137. data/culture/Gemfile +0 -9
  138. data/culture/LICENSE.txt +0 -22
  139. data/culture/README.md +0 -22
  140. data/culture/Rakefile +0 -5
  141. data/culture/SYNC.md +0 -70
  142. data/culture/celluloid-culture.gemspec +0 -18
  143. data/culture/gems/README.md +0 -39
  144. data/culture/gems/dependencies.yml +0 -85
  145. data/culture/gems/loader.rb +0 -101
  146. data/culture/rubocop/README.md +0 -38
  147. data/culture/rubocop/lint.yml +0 -8
  148. data/culture/rubocop/metrics.yml +0 -15
  149. data/culture/rubocop/perf.yml +0 -0
  150. data/culture/rubocop/rubocop.yml +0 -5
  151. data/culture/rubocop/style.yml +0 -57
  152. data/culture/spec/gems_spec.rb +0 -2
  153. data/culture/spec/spec_helper.rb +0 -0
  154. data/culture/spec/sync_spec.rb +0 -2
  155. data/culture/sync.rb +0 -56
  156. data/culture/tasks/rspec.rake +0 -5
  157. data/culture/tasks/rubocop.rake +0 -2
  158. data/lib/celluloid/actor/manager.rb +0 -7
  159. data/lib/celluloid/backported.rb +0 -2
  160. data/lib/celluloid/current.rb +0 -2
  161. data/lib/celluloid/deprecate.rb +0 -21
  162. data/lib/celluloid/fiber.rb +0 -32
  163. data/lib/celluloid/managed.rb +0 -3
  164. data/lib/celluloid/notices.rb +0 -15
  165. data/spec/deprecate/actor_system_spec.rb +0 -72
  166. data/spec/deprecate/block_spec.rb +0 -52
  167. data/spec/deprecate/calls_spec.rb +0 -39
  168. data/spec/deprecate/evented_mailbox_spec.rb +0 -34
  169. data/spec/deprecate/future_spec.rb +0 -32
  170. data/spec/deprecate/internal_pool_spec.rb +0 -4
  171. data/spec/support/env.rb +0 -21
@@ -1,8 +0,0 @@
1
- Lint/HandleExceptions:
2
- Enabled: false
3
-
4
- Lint/LiteralInCondition:
5
- Enabled: false
6
-
7
- Lint/UnusedBlockArgument:
8
- Enabled: false
@@ -1,15 +0,0 @@
1
- Metrics/MethodLength:
2
- CountComments: false
3
- Max: 20
4
-
5
- Metrics/LineLength:
6
- Max: 120
7
-
8
- Metrics/CyclomaticComplexity:
9
- Max: 9
10
-
11
- Metrics/PerceivedComplexity:
12
- Max: 9
13
-
14
- Metrics/AbcSize:
15
- Max: 20
File without changes
@@ -1,5 +0,0 @@
1
- inherit_from:
2
- - lint.yml
3
- - metrics.yml
4
- - style.yml
5
- - perf.yml
@@ -1,57 +0,0 @@
1
- Style/Documentation:
2
- Enabled: false
3
-
4
- Style/ModuleFunction:
5
- Enabled: false
6
-
7
- Style/AndOr:
8
- Enabled: true
9
-
10
- Style/StringLiterals:
11
- Enabled: true
12
- EnforcedStyle: double_quotes
13
-
14
- Style/EachWithObject:
15
- Enabled: true
16
-
17
- Style/InfiniteLoop:
18
- Enabled: false
19
-
20
- Style/SpaceAroundEqualsInParameterDefault:
21
- Enabled: false
22
-
23
- Style/SpaceInsideBlockBraces:
24
- Enabled: false
25
-
26
- Style/AccessModifierIndentation:
27
- Enabled: false
28
-
29
- Style/TrailingComma:
30
- Enabled: true
31
- EnforcedStyleForMultiline: comma
32
-
33
- Style/SpaceInsideBlockBraces:
34
- Enabled: true
35
- EnforcedStyle: space
36
-
37
- Style/SpaceInsideHashLiteralBraces:
38
- Enabled: true
39
- EnforcedStyle: no_space
40
-
41
- Style/EmptyLinesAroundAccessModifier:
42
- Enabled: false
43
-
44
- Style/RescueModifier:
45
- Enabled: false
46
-
47
- Style/GlobalVars:
48
- Enabled: false
49
-
50
- Style/FormatString:
51
- EnforcedStyle: percent
52
-
53
- Style/TrailingUnderscoreVariable:
54
- Enabled: false
55
-
56
- Style/ParallelAssignment:
57
- Enabled: false
@@ -1,2 +0,0 @@
1
- Rspec.describe Celluloid::Gems do
2
- end
File without changes
@@ -1,2 +0,0 @@
1
- Rspec.describe Celluloid::Sync do
2
- end
data/culture/sync.rb DELETED
@@ -1,56 +0,0 @@
1
- require "forwardable"
2
-
3
- module Celluloid
4
- module Sync
5
- class << self
6
- undef gem_path rescue nil
7
- def gem_path
8
- File.expand_path("../../", __FILE__)
9
- end
10
-
11
- undef gem_name rescue nil
12
- def gem_name
13
- Dir["#{File.expand_path('../../', __FILE__)}/*.gemspec"].first.gsub(".gemspec", "").split("/").last
14
- end
15
-
16
- undef gem_name? rescue nil
17
- def gem_name?
18
- !gem_name.nil?
19
- end
20
-
21
- undef lib_path rescue nil
22
- def lib_path
23
- File.expand_path("../../lib", __FILE__)
24
- end
25
-
26
- undef lib_gempath rescue nil
27
- def lib_gempath
28
- "#{lib_path}/#{gem_name.split('-').join('/')}"
29
- end
30
-
31
- undef scenario rescue nil
32
- def scenario
33
- File.basename($PROGRAM_NAME)
34
- end
35
-
36
- undef bundler? rescue nil
37
- def bundler?
38
- scenario == "bundle"
39
- end
40
- end
41
-
42
- fail "Missing gemspec." unless gem_name?
43
- $LOAD_PATH.push(gem_path)
44
- $LOAD_PATH.push(lib_path)
45
-
46
- # TODO: This will likely need to be done differently if INSIDE a cut gem.
47
- if scenario == "bundle"
48
- `cd #{gem_path}/culture; git pull origin master` if ARGV.first == "update"
49
- end
50
-
51
- require("#{gem_path}/culture/gems/loader")
52
- if File.exist?(version = "#{lib_gempath}/version.rb")
53
- require(version)
54
- end
55
- end
56
- end
@@ -1,5 +0,0 @@
1
- require "rspec/core/rake_task"
2
-
3
- RSpec::Core::RakeTask.new(:rcov) do |task|
4
- task.rcov = true
5
- end
@@ -1,2 +0,0 @@
1
- require "rubocop/rake_task"
2
- RuboCop::RakeTask.new
@@ -1,7 +0,0 @@
1
- module Celluloid
2
- class Actor
3
- class Manager
4
- include Celluloid
5
- end
6
- end
7
- end
@@ -1,2 +0,0 @@
1
- $CELLULOID_BACKPORTED = true
2
- require "celluloid/autostart"
@@ -1,2 +0,0 @@
1
- $CELLULOID_BACKPORTED = false
2
- require "celluloid/autostart"
@@ -1,21 +0,0 @@
1
- class Thread
2
- def self.mailbox
3
- Celluloid.mailbox
4
- end
5
-
6
- def self.receive(timeout = nil, &block)
7
- Celluloid.receive(timeout, &block)
8
- end
9
- end
10
-
11
- # TODO: Remove link to Interal::Logger
12
- module Celluloid
13
- SyncCall = Call::Sync
14
- EventedMailbox = Mailbox::Evented
15
- InternalPool = Group::Pool
16
- TaskThread = Task::Threaded
17
- TaskFiber = Task::Fibered
18
- ActorSystem = Actor::System
19
- Task::TerminatedError = TaskTerminated
20
- Task::TimeoutError = TaskTimeout
21
- end
@@ -1,32 +0,0 @@
1
- # Fibers are hard... let's go shopping!
2
- begin
3
- require "fiber"
4
- rescue LoadError => ex
5
- if defined? JRUBY_VERSION
6
- if RUBY_VERSION < "1.9.2"
7
- raise LoadError, "Celluloid requires JRuby 1.9 mode. Please pass the --1.9 flag or set JRUBY_OPTS=--1.9"
8
- end
9
-
10
- # Fibers are broken on JRuby 1.6.5. This works around the issue
11
- if JRUBY_VERSION[/^1\.6\.5/]
12
- require "jruby"
13
- org.jruby.ext.fiber.FiberExtLibrary.new.load(JRuby.runtime, false)
14
- class org.jruby.ext.fiber::ThreadFiber
15
- field_accessor :state
16
- end
17
-
18
- class Fiber
19
- def alive?
20
- JRuby.reference(self).state != org.jruby.ext.fiber.ThreadFiberState::FINISHED
21
- end
22
- end
23
- else
24
- # Just in case subsequent JRuby releases have broken fibers :/
25
- raise ex
26
- end
27
- elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
28
- raise LoadError, "Celluloid requires Rubinius 1.9 mode. Please pass the -X19 flag."
29
- else
30
- raise ex
31
- end
32
- end
@@ -1,3 +0,0 @@
1
- $CELLULOID_BACKPORTED = false
2
- $CELLULOID_MANAGED = true
3
- require "celluloid/autostart"
@@ -1,15 +0,0 @@
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
@@ -1,72 +0,0 @@
1
- RSpec.describe "Deprecated Celluloid::ActorSystem" do
2
- subject { Celluloid::ActorSystem.new }
3
-
4
- class DeprecatedTestActor
5
- include Celluloid
6
- end
7
-
8
- it "supports non-global ActorSystem" do
9
- subject.within do
10
- expect(Celluloid.actor_system).to eq(subject)
11
- end
12
- end
13
-
14
- it "starts default actors" do
15
- subject.start
16
- expect(subject.registered).to eq(Celluloid::ActorSystem::ROOT_SERVICES.map { |r| r[:as] })
17
- subject.shutdown
18
- end
19
-
20
- it "support getting threads" do
21
- subject.start
22
- queue = Queue.new
23
- thread = subject.get_thread do
24
- expect(Celluloid.actor_system).to eq(subject)
25
- queue << nil
26
- end
27
- queue.pop
28
- subject.shutdown
29
- end
30
-
31
- it "allows a stack dump" do
32
- expect(subject.stack_dump).to be_a(Celluloid::StackDump)
33
- end
34
-
35
- it "returns named actors" do
36
- subject.start
37
-
38
- subject.within do
39
- DeprecatedTestActor.supervise_as :test
40
- end
41
-
42
- expect(subject.registered).to include(:test)
43
- subject.shutdown
44
- end
45
-
46
- it "returns running actors" do
47
- expect(subject.running).to be_empty
48
-
49
- first = subject.within do
50
- DeprecatedTestActor.new
51
- end
52
-
53
- second = subject.within do
54
- DeprecatedTestActor.new
55
- end
56
-
57
- expect(subject.running).to eq([first, second])
58
- subject.shutdown
59
- end
60
-
61
- it "shuts down" do
62
- subject.shutdown
63
-
64
- expect { subject.get_thread }
65
- .to raise_error(Celluloid::NotActive)
66
- end
67
-
68
- it "warns nicely when no actor system is started" do
69
- expect { DeprecatedTestActor.new }
70
- .to raise_error("Celluloid is not yet started; use Celluloid.boot")
71
- end
72
- end unless $CELLULOID_BACKPORTED == false
@@ -1,52 +0,0 @@
1
- RSpec.describe "Deprecated Blocks", actor_system: :global do
2
- class DeprecatedBlockActor
3
- include Celluloid
4
-
5
- def initialize(name)
6
- @name = name
7
- end
8
- attr_reader :name
9
-
10
- def ask_for_something(other)
11
- sender_actor = current_actor
12
- $data << [:outside, @name, current_actor.name]
13
- other.do_something_and_callback do |value|
14
- $data << [:yielded, @name, current_actor.name]
15
- $data << receive_result(:self)
16
- $data << current_actor.receive_result(:current_actor)
17
- $data << sender_actor.receive_result(:sender)
18
- "somevalue"
19
- end
20
- end
21
-
22
- def do_something_and_callback
23
- $data << [:something, @name, current_actor.name]
24
- $data << yield(:foo)
25
- end
26
-
27
- def receive_result(result)
28
- [result, @name, current_actor.name]
29
- end
30
- end
31
-
32
- it "works" do
33
- $data = []
34
-
35
- a1 = DeprecatedBlockActor.new("one")
36
- a2 = DeprecatedBlockActor.new("two")
37
-
38
- a1.ask_for_something a2
39
-
40
- expected = [
41
- [:outside, "one", "one"],
42
- [:something, "two", "two"],
43
- [:yielded, "one", "one"],
44
- [:self, "one", "one"],
45
- [:current_actor, "one", "one"],
46
- [:sender, "one", "one"],
47
- "somevalue",
48
- ]
49
-
50
- expect($data).to eq(expected)
51
- end
52
- end unless $CELLULOID_BACKPORTED == false
@@ -1,39 +0,0 @@
1
- RSpec.describe "Deprecated Celluloid::SyncCall", actor_system: :global do
2
- subject { Celluloid::SyncCall.new }
3
-
4
- let(:actor) { DeprecatedCallExampleActor.new }
5
-
6
- context "when obj does not respond to a method" do
7
- it "raises a NoMethodError" do
8
- expect do
9
- actor.the_method_that_wasnt_there
10
- end.to raise_exception(NoMethodError)
11
- expect(actor).to be_alive
12
- end
13
-
14
- context "when obj raises during inspect" do
15
- it "should emulate obj.inspect" do
16
- expect(actor).to_not receive(:inspect)
17
- expect { actor.no_such_method }.to raise_exception(
18
- NoMethodError,
19
- /undefined method `no_such_method' for #\<DeprecatedCallExampleActor:0x[a-f0-9]+>/,
20
- )
21
- end
22
- end
23
- end
24
-
25
- it "aborts with ArgumentError when a method is called with too many arguments" do
26
- expect do
27
- actor.actual_method("with too many arguments")
28
- end.to raise_exception(ArgumentError)
29
-
30
- expect(actor).to be_alive
31
- end
32
-
33
- it "preserves call chains across synchronous calls" do
34
- actor2 = DeprecatedCallExampleActor.new(actor)
35
-
36
- uuid, next_actor_uuid = actor2.chained_call_ids
37
- expect(uuid).to eq next_actor_uuid
38
- end
39
- end unless $CELLULOID_BACKPORTED == false
@@ -1,34 +0,0 @@
1
- unless $CELLULOID_BACKPORTED == false
2
- class DeprecatedTestEventedMailbox < Celluloid::Mailbox::Evented
3
- class Reactor
4
- def initialize
5
- @condition = ConditionVariable.new
6
- @mutex = Mutex.new
7
- end
8
-
9
- def wakeup
10
- @mutex.synchronize do
11
- @condition.signal
12
- end
13
- end
14
-
15
- def run_once(timeout)
16
- @mutex.synchronize do
17
- @condition.wait(@mutex, timeout)
18
- end
19
- end
20
-
21
- def shutdown
22
- end
23
- end
24
-
25
- def initialize
26
- super(Reactor)
27
- end
28
- end
29
-
30
- RSpec.describe "Deprecated Celluloid::Mailbox::Evented" do
31
- subject { DeprecatedTestEventedMailbox.new }
32
- it_behaves_like "a Celluloid Mailbox"
33
- end
34
- end