1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
RSpec.shared_examples "a Celluloid Stack" do
let(:actor_system) { Celluloid::Actor::System.new }
let(:threads) { Queue.new }
before(:each) do
items = 0
[Celluloid::Task::Fibered, Celluloid::Task::Threaded].each do |task_klass|
create_async_blocking_actor(task_klass)
items += 1
end
@active_thread = create_thread_with_role(threads, :other_thing)
items += 1
@idle_thread = create_thread_with_role(threads, :idle_thing)
items += 1
# StackWaiter for each thread to add itself to the queue
tmp = Queue.new
items.times do
th = Timeout.timeout(4) { threads.pop }
tmp << th
end
expect(threads).to be_empty
# put threads back into the queue for killing
threads << tmp.pop until tmp.empty?
end
after do
StackWaiter.no_longer
actor_system.shutdown
end
describe "#actors" do
it "should include all actors" do
expect(subject.actors.size).to eq(2)
end
end
describe "#threads" do
# TODO: this spec should use mocks because it's non-deterministict
it "should include threads that are not actors" do
# TODO: Assess need for bypassing StackWaiter.forever's QUEUE.pop after #670 & #678
# NOTE: Pool#each doesn't guarantee to contain the newly started thread
# because the actor's methods (which create and store the thread handle)
# are started asynchronously.
#
# The mutexes in InternalPool especially can cause additional delay -
# causing Pool#get to wait for IPool#each to free the mutex before the
# new thread can be stored.
#
# And, Internals::StackDump#threads is cached, so we have to reconstruct the
# Internals::StackDump until it matches reality.
#
# Also, the actual number of threads and how InternalPool juggles them is
# non deterministic to begin with:
#
# 2 actors
# -> *0-1 task threads
#
# *1 idle thread
# *1 active thread
#
# Together: 3-4 threads
# Pool somehow doesn't create extra tasks
# 5 is on JRuby-head
expected = Celluloid.group_class == Celluloid::Group::Pool ? [3, 4] : [3, 4, 5, 6]
expect(expected).to include(subject.threads.size)
end
it "should include idle threads" do
expect(subject.threads.map(&:thread_id)).to include(@idle_thread.object_id)
end
it "should include threads checked out of the group for roles other than :actor" do
expect(subject.threads.map(&:thread_id)).to include(@active_thread.object_id)
end
it "should have the correct roles" do
expect(subject.threads.map(&:role)).to include(:idle_thing, :other_thing)
end
end
end
|