summaryrefslogtreecommitdiff
path: root/cont.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-10-12 12:59:05 +1300
committerGitHub <noreply@github.com>2022-10-12 12:59:05 +1300
commitced1d172804b6dfe39aa31a323ffab80a25223b9 (patch)
tree6c030bd708a935deb164c9ec69df5f58f9d39df6 /cont.c
parent467992ee35b59577ddb53f1323b19af3f3e3d134 (diff)
downloadruby-ced1d172804b6dfe39aa31a323ffab80a25223b9.tar.gz
Improvements to IO::Buffer implementation and documentation. (#6525)
Diffstat (limited to 'cont.c')
-rw-r--r--cont.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/cont.c b/cont.c
index 499e1e7910..39f0fc8171 100644
--- a/cont.c
+++ b/cont.c
@@ -2410,20 +2410,34 @@ rb_fiber_transfer(VALUE fiber_value, int argc, const VALUE *argv)
VALUE
rb_fiber_blocking_p(VALUE fiber)
{
- return RBOOL(fiber_ptr(fiber)->blocking != 0);
+ return RBOOL(fiber_ptr(fiber)->blocking);
}
static VALUE
-fiber_blocking_yield(VALUE fiber)
+fiber_blocking_yield(VALUE fiber_value)
{
- fiber_ptr(fiber)->blocking += 1;
- return rb_yield(fiber);
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+ rb_thread_t * volatile th = fiber->cont.saved_ec.thread_ptr;
+
+ // fiber->blocking is `unsigned int : 1`, so we use it as a boolean:
+ fiber->blocking = 1;
+
+ // Once the fiber is blocking, and current, we increment the thread blocking state:
+ th->blocking += 1;
+
+ return rb_yield(fiber_value);
}
static VALUE
-fiber_blocking_ensure(VALUE fiber)
+fiber_blocking_ensure(VALUE fiber_value)
{
- fiber_ptr(fiber)->blocking -= 1;
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+ rb_thread_t * volatile th = fiber->cont.saved_ec.thread_ptr;
+
+ // We are no longer blocking:
+ fiber->blocking = 0;
+ th->blocking -= 1;
+
return Qnil;
}
@@ -2440,8 +2454,15 @@ fiber_blocking_ensure(VALUE fiber)
VALUE
rb_fiber_blocking(VALUE class)
{
- VALUE fiber = rb_fiber_current();
- return rb_ensure(fiber_blocking_yield, fiber, fiber_blocking_ensure, fiber);
+ VALUE fiber_value = rb_fiber_current();
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
+
+ // If we are already blocking, this is essentially a no-op:
+ if (fiber->blocking) {
+ return rb_yield(fiber_value);
+ } else {
+ return rb_ensure(fiber_blocking_yield, fiber_value, fiber_blocking_ensure, fiber_value);
+ }
}
/*