Skip to content

Commit

Permalink
std specs: use isolated execution context instead of bare thread
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbaddaden committed Jan 7, 2025
1 parent 3bb10e5 commit a230257
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 33 deletions.
21 changes: 7 additions & 14 deletions spec/std/execution_context/global_queue_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "./spec_helper"
require "../../support/thread"

describe ExecutionContext::GlobalQueue do
it "#initialize" do
Expand Down Expand Up @@ -98,10 +99,10 @@ describe ExecutionContext::GlobalQueue do
increments = 15
queue = ExecutionContext::GlobalQueue.new(Thread::Mutex.new)
ready = Thread::WaitGroup.new(n)
shutdown = Thread::WaitGroup.new(n)
threads = Array(Thread).new(n)

n.times do |i|
Thread.new(name: "ONE-#{i}") do |thread|
threads << new_thread(name: "ONE-#{i}") do
slept = 0
ready.done

Expand All @@ -117,10 +118,6 @@ describe ExecutionContext::GlobalQueue do
break
end
end
rescue exception
Crystal::System.print_error "\nthread: #{thread.name}: exception: #{exception}"
ensure
shutdown.done
end
end
ready.wait
Expand All @@ -130,7 +127,7 @@ describe ExecutionContext::GlobalQueue do
Thread.sleep(10.nanoseconds) if i % 10 == 9
end

shutdown.wait
threads.each(&.join)

# must have dequeued each fiber exactly X times
fibers.each { |fc| fc.counter.should eq(increments) }
Expand All @@ -146,10 +143,10 @@ describe ExecutionContext::GlobalQueue do

queue = ExecutionContext::GlobalQueue.new(Thread::Mutex.new)
ready = Thread::WaitGroup.new(n)
shutdown = Thread::WaitGroup.new(n)
threads = Array(Thread).new(n)

n.times do |i|
Thread.new(name: "BULK-#{i}") do |thread|
threads << new_thread("BULK-#{i}") do
slept = 0

r = ExecutionContext::Runnables(3).new(queue)
Expand Down Expand Up @@ -200,10 +197,6 @@ describe ExecutionContext::GlobalQueue do
slept += 1
Thread.sleep(1.nanosecond) # don't burn CPU
end
rescue exception
Crystal::System.print_error "\nthread #{thread.name} raised: #{exception}"
ensure
shutdown.done
end
end
ready.wait
Expand All @@ -216,7 +209,7 @@ describe ExecutionContext::GlobalQueue do
Thread.sleep(10.nanoseconds) if i % 4 == 3
end

shutdown.wait
threads.each(&.join)

# must have dequeued each fiber exactly X times (no less, no more)
fibers.each { |fc| fc.counter.should eq(increments) }
Expand Down
11 changes: 4 additions & 7 deletions spec/std/execution_context/runnables_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "./spec_helper"
require "../../support/thread"

describe ExecutionContext::Runnables do
it "#initialize" do
Expand Down Expand Up @@ -190,14 +191,14 @@ describe ExecutionContext::Runnables do

global_queue = ExecutionContext::GlobalQueue.new(Thread::Mutex.new)
ready = Thread::WaitGroup.new(n)
shutdown = Thread::WaitGroup.new(n)
threads = Array(Thread).new(n)

all_runnables = Array(ExecutionContext::Runnables(16)).new(n) do
ExecutionContext::Runnables(16).new(global_queue)
end

n.times do |i|
Thread.new(name: "RUN-#{i}") do |thread|
threads << new_thread(name: "RUN-#{i}") do
runnables = all_runnables[i]
slept = 0

Expand Down Expand Up @@ -239,10 +240,6 @@ describe ExecutionContext::Runnables do
slept += 1
Thread.sleep(1.nanosecond) # don't burn CPU
end
rescue exception
Crystal::System.print_error "\nthread #{thread.name} raised: #{exception}"
ensure
shutdown.done
end
end
ready.wait
Expand All @@ -255,7 +252,7 @@ describe ExecutionContext::Runnables do
Thread.sleep(10.nanoseconds) if i % 2 == 1
end

shutdown.wait
threads.map(&.join)

# must have dequeued each fiber exactly X times (no less, no more)
fibers.each { |fc| fc.counter.should eq(increments) }
Expand Down
3 changes: 2 additions & 1 deletion spec/std/file_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "./spec_helper"
require "../support/thread"

private def it_raises_on_null_byte(operation, file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block)
it "errors on #{operation}", file, line, end_line do
Expand Down Expand Up @@ -109,7 +110,7 @@ describe "File" do
# thread or process also opened the file; we should pass
# O_NONBLOCK to the open(2) call itself, not afterwards
file = nil
Thread.new { file = File.new(path, "w", blocking: nil) }
new_thread { file = File.new(path, "w", blocking: nil) }

begin
File.open(path, "r", blocking: false) do |file|
Expand Down
7 changes: 4 additions & 3 deletions spec/std/thread/condition_variable_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "../spec_helper"
require "../../support/thread"

# interpreter doesn't support threads yet (#14287)
pending_interpreted describe: Thread::ConditionVariable do
Expand All @@ -7,7 +8,7 @@ pending_interpreted describe: Thread::ConditionVariable do
cond = Thread::ConditionVariable.new

mutex.synchronize do
Thread.new do
new_thread do
mutex.synchronize { cond.signal }
end

Expand All @@ -22,7 +23,7 @@ pending_interpreted describe: Thread::ConditionVariable do
waiting = 0

5.times do
Thread.new do
new_thread do
mutex.synchronize do
waiting += 1
cv1.wait(mutex)
Expand Down Expand Up @@ -78,7 +79,7 @@ pending_interpreted describe: Thread::ConditionVariable do
cond = Thread::ConditionVariable.new

mutex.synchronize do
Thread.new do
new_thread do
mutex.synchronize { cond.signal }
end

Expand Down
7 changes: 4 additions & 3 deletions spec/std/thread/mutex_spec.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "../spec_helper"
require "../../support/thread"

# interpreter doesn't support threads yet (#14287)
pending_interpreted describe: Thread::Mutex do
Expand All @@ -7,7 +8,7 @@ pending_interpreted describe: Thread::Mutex do
mutex = Thread::Mutex.new

threads = Array.new(10) do
Thread.new do
new_thread do
mutex.synchronize { a += 1 }
end
end
Expand All @@ -22,15 +23,15 @@ pending_interpreted describe: Thread::Mutex do
mutex.try_lock.should be_false
expect_raises(RuntimeError) { mutex.lock }
mutex.unlock
Thread.new { mutex.synchronize { } }.join
new_thread { mutex.synchronize { } }.join
end

it "won't unlock from another thread" do
mutex = Thread::Mutex.new
mutex.lock

expect_raises(RuntimeError) do
Thread.new { mutex.unlock }.join
new_thread { mutex.unlock }.join
end

mutex.unlock
Expand Down
11 changes: 6 additions & 5 deletions spec/std/thread_spec.cr
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
require "./spec_helper"
require "../support/thread"

# interpreter doesn't support threads yet (#14287)
pending_interpreted describe: Thread do
it "allows passing an argumentless fun to execute" do
a = 0
thread = Thread.new { a = 1; 10 }
thread = new_thread { a = 1; 10 }
thread.join
a.should eq(1)
end

it "raises inside thread and gets it on join" do
thread = Thread.new { raise "OH NO" }
thread = new_thread { raise "OH NO" }
expect_raises Exception, "OH NO" do
thread.join
end
end

it "returns current thread object" do
current = nil
thread = Thread.new { current = Thread.current }
thread = new_thread { current = Thread.current }
thread.join
current.should be(thread)
current.should_not be(Thread.current)
Expand All @@ -31,7 +32,7 @@ pending_interpreted describe: Thread do
it "yields the processor" do
done = false

thread = Thread.new do
thread = new_thread do
3.times { Thread.yield }
done = true
end
Expand All @@ -55,7 +56,7 @@ pending_interpreted describe: Thread do
{% end %}

name = nil
thread = Thread.new(name: "some-name") do
thread = new_thread(name: "some-name") do
name = Thread.current.name
end
thread.name.should eq("some-name")
Expand Down
9 changes: 9 additions & 0 deletions spec/support/thread.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% begin %}
def new_thread(name = nil, &block) : Thread
{% if flag?(:execution_context) %}
ExecutionContext::Isolated.new(name: name || "SPEC") { block.call }.@thread
{% else %}
Thread.new(name) { block.call }
{% end %}
end
{% end %}

0 comments on commit a230257

Please sign in to comment.