summaryrefslogtreecommitdiff
path: root/cont.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-10-06 23:00:49 +1300
committerGitHub <noreply@github.com>2022-10-06 23:00:49 +1300
commite696ec67ac7bd14ff8436f9ee7724c17c5bf6689 (patch)
treef1388ed0cc30ceec2e5febf316c3897afa01b9ad /cont.c
parent75a53f6be0bdd02fcf70a352892e085a02995cf9 (diff)
Introduce `Fiber.blocking{}` for bypassing the fiber scheduler. (#6498)
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
Diffstat (limited to 'cont.c')
-rw-r--r--cont.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/cont.c b/cont.c
index 19e719ccd9..499e1e7910 100644
--- a/cont.c
+++ b/cont.c
@@ -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);