diff options
author | Jean Boussier <[email protected]> | 2022-07-26 17:40:00 +0200 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2022-08-02 11:04:28 +0200 |
commit | e3aabe93aae87a60ba7b8f1a0fd590534647e352 (patch) | |
tree | 3f5c15b61c9914c7e1a34ad56d042dcf70024f75 /thread.c | |
parent | ec3f59309e3f08339c4c76a6881901580801d6cd (diff) |
Implement Queue#pop(timeout: sec)
[Feature #18774]
As well as `SizedQueue#pop(timeout: sec)`
If both `non_block=true` and `timeout:` are supplied, ArgumentError
is raised.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6185
Diffstat (limited to 'thread.c')
-rw-r--r-- | thread.c | 35 |
1 files changed, 31 insertions, 4 deletions
@@ -132,7 +132,7 @@ rb_thread_local_storage(VALUE thread) static int sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl); static void sleep_forever(rb_thread_t *th, unsigned int fl); -static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker); +static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker, VALUE timeout, rb_hrtime_t end); static int rb_threadptr_dead(rb_thread_t *th); static void rb_check_deadlock(rb_ractor_t *r); static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th); @@ -1328,6 +1328,28 @@ sleep_hrtime(rb_thread_t *th, rb_hrtime_t rel, unsigned int fl) return woke; } +static int +sleep_hrtime_until(rb_thread_t *th, rb_hrtime_t end, unsigned int fl) +{ + enum rb_thread_status prev_status = th->status; + int woke; + rb_hrtime_t rel = rb_hrtime_sub(end, rb_hrtime_now()); + + th->status = THREAD_STOPPED; + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + while (th->status == THREAD_STOPPED) { + native_sleep(th, &rel); + woke = vm_check_ints_blocking(th->ec); + if (woke && !(fl & SLEEP_SPURIOUS_CHECK)) + break; + if (hrtime_update_expire(&rel, end)) + break; + woke = 1; + } + th->status = prev_status; + return woke; +} + void rb_thread_sleep_forever(void) { @@ -1355,15 +1377,20 @@ rb_thread_sleep_interruptible(void) } static void -rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker) +rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker, VALUE timeout, rb_hrtime_t end) { VALUE scheduler = rb_fiber_scheduler_current(); if (scheduler != Qnil) { - rb_fiber_scheduler_block(scheduler, blocker, Qnil); + rb_fiber_scheduler_block(scheduler, blocker, timeout); } else { RUBY_DEBUG_LOG("%s", ""); - sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE); + if (end) { + sleep_hrtime_until(GET_THREAD(), end, SLEEP_SPURIOUS_CHECK); + } + else { + sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE); + } } } |