diff --git a/crates/rb-sys-tests/src/stable_api_test.rs b/crates/rb-sys-tests/src/stable_api_test.rs index 4bfbef85..8c3156ca 100644 --- a/crates/rb-sys-tests/src/stable_api_test.rs +++ b/crates/rb-sys-tests/src/stable_api_test.rs @@ -647,3 +647,11 @@ parity_test!( }, expected: true ); + +parity_test!( + name: test_rb_thread_sleep, + func: thread_sleep, + data_factory: { + std::time::Duration::from_millis(100) + } +); diff --git a/crates/rb-sys/src/stable_api.rs b/crates/rb-sys/src/stable_api.rs index 424e578c..10b34f9c 100644 --- a/crates/rb-sys/src/stable_api.rs +++ b/crates/rb-sys/src/stable_api.rs @@ -15,6 +15,7 @@ use crate::VALUE; use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; pub trait StableApiDefinition { @@ -171,6 +172,9 @@ pub trait StableApiDefinition { /// access to underlying flags of the RString. The caller must ensure that /// the `VALUE` is a valid pointer to an RString. unsafe fn rstring_interned_p(&self, obj: VALUE) -> bool; + + /// Blocks the current thread until the given duration has passed. + fn thread_sleep(&self, duration: Duration); } #[cfg(stable_api_enable_compiled_mod)] diff --git a/crates/rb-sys/src/stable_api/compiled.c b/crates/rb-sys/src/stable_api/compiled.c index 3d5cc134..db89dc1f 100644 --- a/crates/rb-sys/src/stable_api/compiled.c +++ b/crates/rb-sys/src/stable_api/compiled.c @@ -115,3 +115,9 @@ impl_rstring_interned_p(VALUE obj) { return !(FL_TEST(obj, RSTRING_FSTR) == 0); } + +void +impl_thread_sleep(struct timeval time) { + rb_thread_wait_for(time); +} + diff --git a/crates/rb-sys/src/stable_api/compiled.rs b/crates/rb-sys/src/stable_api/compiled.rs index 44284b1b..527fabd0 100644 --- a/crates/rb-sys/src/stable_api/compiled.rs +++ b/crates/rb-sys/src/stable_api/compiled.rs @@ -1,8 +1,9 @@ use super::StableApiDefinition; -use crate::{ruby_value_type, VALUE}; +use crate::{ruby_value_type, timeval, VALUE}; use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[allow(dead_code)] @@ -75,6 +76,9 @@ extern "C" { #[link_name = "impl_rstring_interned_p"] fn impl_rstring_interned_p(obj: VALUE) -> bool; + + #[link_name = "impl_thread_sleep"] + fn impl_thread_sleep(interval: timeval); } pub struct Definition; @@ -192,7 +196,21 @@ impl StableApiDefinition for Definition { impl_integer_type_p(obj) } + #[inline] unsafe fn rstring_interned_p(&self, obj: VALUE) -> bool { impl_rstring_interned_p(obj) } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { impl_thread_sleep(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_2_6.rs b/crates/rb-sys/src/stable_api/ruby_2_6.rs index 4e39effe..0407f8d7 100644 --- a/crates/rb-sys/src/stable_api/ruby_2_6.rs +++ b/crates/rb-sys/src/stable_api/ruby_2_6.rs @@ -9,6 +9,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_2_6))] @@ -103,7 +104,7 @@ impl StableApiDefinition for Definition { if self.special_const_p(obj) { true } else { - let rbasic = obj as *const crate::Rbasic; + let rbasic = obj as *const crate::RBasic; ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0 } } @@ -262,4 +263,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_2_7.rs b/crates/rb-sys/src/stable_api/ruby_2_7.rs index 3da2e517..e5a1eb12 100644 --- a/crates/rb-sys/src/stable_api/ruby_2_7.rs +++ b/crates/rb-sys/src/stable_api/ruby_2_7.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_2_7))] @@ -262,4 +263,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_3_0.rs b/crates/rb-sys/src/stable_api/ruby_3_0.rs index 51b9792f..cd22ae7a 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_0.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_0.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_3_0))] @@ -270,4 +271,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_3_1.rs b/crates/rb-sys/src/stable_api/ruby_3_1.rs index 0124db70..a604426f 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_1.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_1.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_3_1))] @@ -263,4 +264,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_3_2.rs b/crates/rb-sys/src/stable_api/ruby_3_2.rs index 2ab62269..52e0067e 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_2.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_2.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_3_2))] @@ -261,4 +262,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_3_3.rs b/crates/rb-sys/src/stable_api/ruby_3_3.rs index fb05f8e3..d068fac1 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_3.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_3.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_3_3))] @@ -254,4 +255,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } } diff --git a/crates/rb-sys/src/stable_api/ruby_3_4.rs b/crates/rb-sys/src/stable_api/ruby_3_4.rs index 3f370a3d..74a82f5b 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_4.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_4.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ os::raw::{c_char, c_long}, ptr::NonNull, + time::Duration, }; #[cfg(not(ruby_eq_3_4))] @@ -254,4 +255,17 @@ impl StableApiDefinition for Definition { (flags & crate::ruby_rstring_flags::RSTRING_FSTR as VALUE) != 0 } + + #[inline] + fn thread_sleep(&self, duration: Duration) { + let seconds = duration.as_secs() as _; + let microseconds = duration.subsec_micros() as _; + + let time = crate::timeval { + tv_sec: seconds, + tv_usec: microseconds, + }; + + unsafe { crate::rb_thread_wait_for(time) } + } }