Introduce Fiber.blocking{}
for bypassing the fiber scheduler. (#6498)
This commit is contained in:
parent
75a53f6be0
commit
e696ec67ac
Notes:
git
2022-10-06 19:01:13 +09:00
Merged-By: ioquatix <samuel@codeotaku.com>
32
cont.c
32
cont.c
@ -2413,6 +2413,37 @@ rb_fiber_blocking_p(VALUE fiber)
|
|||||||
return RBOOL(fiber_ptr(fiber)->blocking != 0);
|
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:
|
* call-seq:
|
||||||
* Fiber.blocking? -> false or 1
|
* Fiber.blocking? -> false or 1
|
||||||
@ -3303,6 +3334,7 @@ Init_Cont(void)
|
|||||||
rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
|
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, "yield", rb_fiber_s_yield, -1);
|
||||||
rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
|
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, "initialize", rb_fiber_initialize, -1);
|
||||||
rb_define_method(rb_cFiber, "blocking?", rb_fiber_blocking_p, 0);
|
rb_define_method(rb_cFiber, "blocking?", rb_fiber_blocking_p, 0);
|
||||||
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
|
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
|
||||||
|
@ -60,3 +60,20 @@ ruby_version_is "3.0" do
|
|||||||
end
|
end
|
||||||
end
|
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
|
||||||
|
@ -27,6 +27,17 @@ class TestFiberScheduler < Test::Unit::TestCase
|
|||||||
refute f.blocking?
|
refute f.blocking?
|
||||||
end
|
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
|
def test_closed_at_thread_exit
|
||||||
scheduler = Scheduler.new
|
scheduler = Scheduler.new
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user