1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Introduce Fiber.blocking{} for bypassing the fiber scheduler. (#6498)

This commit is contained in:
Samuel Williams 2022-10-06 23:00:49 +13:00 committed by GitHub
parent 75a53f6be0
commit e696ec67ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2022-10-06 19:01:13 +09:00
Merged-By: ioquatix <samuel@codeotaku.com>
3 changed files with 60 additions and 0 deletions

32
cont.c
View file

@ -2413,6 +2413,37 @@ rb_fiber_blocking_p(VALUE fiber)
return RBOOL(fiber_ptr(fiber)->blocking != 0);
}
static VALUE
fiber_blocking_yield(VALUE fiber)
{
fiber_ptr(fiber)->blocking += 1;
return rb_yield(fiber);
}
static VALUE
fiber_blocking_ensure(VALUE fiber)
{
fiber_ptr(fiber)->blocking -= 1;
return Qnil;
}
/*
* call-seq:
* Fiber.blocking{|fiber| ...} -> result
*
* Forces the fiber to be blocking for the duration of the block. Returns the
* result of the block.
*
* See the "Non-blocking fibers" section in class docs for details.
*
*/
VALUE
rb_fiber_blocking(VALUE class)
{
VALUE fiber = rb_fiber_current();
return rb_ensure(fiber_blocking_yield, fiber, fiber_blocking_ensure, fiber);
}
/*
* call-seq:
* Fiber.blocking? -> false or 1
@ -3303,6 +3334,7 @@ Init_Cont(void)
rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
rb_define_singleton_method(rb_cFiber, "blocking", rb_fiber_blocking, 0);
rb_define_method(rb_cFiber, "initialize", rb_fiber_initialize, -1);
rb_define_method(rb_cFiber, "blocking?", rb_fiber_blocking_p, 0);
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);

View file

@ -60,3 +60,20 @@ ruby_version_is "3.0" do
end
end
end
ruby_version_is "3.2" do
describe "Fiber.blocking" do
context "when fiber is non-blocking" do
it "can become blocking" do
fiber = Fiber.new(blocking: false) do
Fiber.blocking do |fiber|
fiber.blocking? ? :blocking : :non_blocking
end
end
blocking = fiber.resume
blocking.should == :blocking
end
end
end
end

View file

@ -27,6 +27,17 @@ class TestFiberScheduler < Test::Unit::TestCase
refute f.blocking?
end
def test_fiber_blocking
f = Fiber.new(blocking: false) do
fiber = Fiber.current
refute fiber.blocking?
Fiber.blocking do |_fiber|
assert_equal fiber, _fiber
assert fiber.blocking?
end
end
end
def test_closed_at_thread_exit
scheduler = Scheduler.new