From bcb5aeb5d2c432ccb1e5e2385189ed15599e8ba8 Mon Sep 17 00:00:00 2001 From: Julien Portalier Date: Sun, 16 Jun 2024 10:59:34 +0200 Subject: [PATCH] Add `Thread.sleep(Time::Span)` (#14715) Blocks the current thread for the given duration. --- src/crystal/system/thread.cr | 8 ++++++++ src/crystal/system/unix/pthread.cr | 12 ++++++++++++ src/crystal/system/wasi/thread.cr | 12 ++++++++++++ src/crystal/system/win32/thread.cr | 4 ++++ src/lib_c/aarch64-android/c/time.cr | 1 + src/lib_c/aarch64-darwin/c/time.cr | 1 + src/lib_c/aarch64-linux-gnu/c/time.cr | 1 + src/lib_c/aarch64-linux-musl/c/time.cr | 1 + src/lib_c/arm-linux-gnueabihf/c/time.cr | 1 + src/lib_c/i386-linux-gnu/c/time.cr | 1 + src/lib_c/i386-linux-musl/c/time.cr | 1 + src/lib_c/wasm32-wasi/c/time.cr | 1 + src/lib_c/x86_64-darwin/c/time.cr | 1 + src/lib_c/x86_64-dragonfly/c/time.cr | 1 + src/lib_c/x86_64-freebsd/c/time.cr | 1 + src/lib_c/x86_64-linux-gnu/c/time.cr | 1 + src/lib_c/x86_64-linux-musl/c/time.cr | 1 + src/lib_c/x86_64-netbsd/c/time.cr | 1 + src/lib_c/x86_64-openbsd/c/time.cr | 1 + src/lib_c/x86_64-solaris/c/time.cr | 1 + 20 files changed, 52 insertions(+) diff --git a/src/crystal/system/thread.cr b/src/crystal/system/thread.cr index 03b00f2779f4..d9dc6acf17dc 100644 --- a/src/crystal/system/thread.cr +++ b/src/crystal/system/thread.cr @@ -14,6 +14,8 @@ module Crystal::System::Thread # def self.current_thread=(thread : ::Thread) + # def self.sleep(time : ::Time::Span) : Nil + # private def system_join : Exception? # private def system_close @@ -99,6 +101,12 @@ class Thread end end + # Blocks the current thread for the duration of *time*. Clock precision is + # dependent on the operating system and hardware. + def self.sleep(time : Time::Span) : Nil + Crystal::System::Thread.sleep(time) + end + # Returns the Thread object associated to the running system thread. def self.current : Thread Crystal::System::Thread.current_thread diff --git a/src/crystal/system/unix/pthread.cr b/src/crystal/system/unix/pthread.cr index 4b357b04281c..d38e52ee012a 100644 --- a/src/crystal/system/unix/pthread.cr +++ b/src/crystal/system/unix/pthread.cr @@ -75,6 +75,18 @@ module Crystal::System::Thread end {% end %} + def self.sleep(time : ::Time::Span) : Nil + req = uninitialized LibC::Timespec + req.tv_sec = typeof(req.tv_sec).new(time.seconds) + req.tv_nsec = typeof(req.tv_nsec).new(time.nanoseconds) + + loop do + return if LibC.nanosleep(pointerof(req), out rem) == 0 + raise RuntimeError.from_errno("nanosleep() failed") unless Errno.value == Errno::EINTR + req = rem + end + end + private def system_join : Exception? ret = GC.pthread_join(@system_handle) RuntimeError.from_os_error("pthread_join", Errno.new(ret)) unless ret == 0 diff --git a/src/crystal/system/wasi/thread.cr b/src/crystal/system/wasi/thread.cr index 0e641faba785..6f0c0cbe8260 100644 --- a/src/crystal/system/wasi/thread.cr +++ b/src/crystal/system/wasi/thread.cr @@ -15,6 +15,18 @@ module Crystal::System::Thread class_property current_thread : ::Thread { ::Thread.new } + def self.sleep(time : ::Time::Span) : Nil + req = uninitialized LibC::Timespec + req.tv_sec = typeof(req.tv_sec).new(time.seconds) + req.tv_nsec = typeof(req.tv_nsec).new(time.nanoseconds) + + loop do + return if LibC.nanosleep(pointerof(req), out rem) == 0 + raise RuntimeError.from_errno("nanosleep() failed") unless Errno.value == Errno::EINTR + req = rem + end + end + private def system_join : Exception? NotImplementedError.new("Crystal::System::Thread#system_join") end diff --git a/src/crystal/system/win32/thread.cr b/src/crystal/system/win32/thread.cr index 9507e332b422..ddfe3298b20a 100644 --- a/src/crystal/system/win32/thread.cr +++ b/src/crystal/system/win32/thread.cr @@ -51,6 +51,10 @@ module Crystal::System::Thread @@current_thread end + def self.sleep(time : ::Time::Span) : Nil + LibC.Sleep(time.total_milliseconds.to_i.clamp(1..)) + end + private def system_join : Exception? if LibC.WaitForSingleObject(@system_handle, LibC::INFINITE) != LibC::WAIT_OBJECT_0 return RuntimeError.from_winerror("WaitForSingleObject") diff --git a/src/lib_c/aarch64-android/c/time.cr b/src/lib_c/aarch64-android/c/time.cr index 3108f2e94bff..8f8b81291f0d 100644 --- a/src/lib_c/aarch64-android/c/time.cr +++ b/src/lib_c/aarch64-android/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(__t : TimeT*, __tm : Tm*) : Tm* fun localtime_r(__t : TimeT*, __tm : Tm*) : Tm* fun mktime(__tm : Tm*) : TimeT + fun nanosleep(__req : Timespec*, __rem : Timespec*) : Int fun tzset : Void fun timegm(__tm : Tm*) : TimeT diff --git a/src/lib_c/aarch64-darwin/c/time.cr b/src/lib_c/aarch64-darwin/c/time.cr index e20477a6a004..7e76fb969fbe 100644 --- a/src/lib_c/aarch64-darwin/c/time.cr +++ b/src/lib_c/aarch64-darwin/c/time.cr @@ -23,6 +23,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/aarch64-linux-gnu/c/time.cr b/src/lib_c/aarch64-linux-gnu/c/time.cr index b93b8e698dd9..710d477e269b 100644 --- a/src/lib_c/aarch64-linux-gnu/c/time.cr +++ b/src/lib_c/aarch64-linux-gnu/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(timer : TimeT*, tp : Tm*) : Tm* fun localtime_r(timer : TimeT*, tp : Tm*) : Tm* fun mktime(tp : Tm*) : TimeT + fun nanosleep(req : Timespec*, rem : Timespec*) : Int fun tzset : Void fun timegm(tp : Tm*) : TimeT diff --git a/src/lib_c/aarch64-linux-musl/c/time.cr b/src/lib_c/aarch64-linux-musl/c/time.cr index 22fdf7a86ebf..f687c8b35db4 100644 --- a/src/lib_c/aarch64-linux-musl/c/time.cr +++ b/src/lib_c/aarch64-linux-musl/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/arm-linux-gnueabihf/c/time.cr b/src/lib_c/arm-linux-gnueabihf/c/time.cr index b93b8e698dd9..710d477e269b 100644 --- a/src/lib_c/arm-linux-gnueabihf/c/time.cr +++ b/src/lib_c/arm-linux-gnueabihf/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(timer : TimeT*, tp : Tm*) : Tm* fun localtime_r(timer : TimeT*, tp : Tm*) : Tm* fun mktime(tp : Tm*) : TimeT + fun nanosleep(req : Timespec*, rem : Timespec*) : Int fun tzset : Void fun timegm(tp : Tm*) : TimeT diff --git a/src/lib_c/i386-linux-gnu/c/time.cr b/src/lib_c/i386-linux-gnu/c/time.cr index b93b8e698dd9..710d477e269b 100644 --- a/src/lib_c/i386-linux-gnu/c/time.cr +++ b/src/lib_c/i386-linux-gnu/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(timer : TimeT*, tp : Tm*) : Tm* fun localtime_r(timer : TimeT*, tp : Tm*) : Tm* fun mktime(tp : Tm*) : TimeT + fun nanosleep(req : Timespec*, rem : Timespec*) : Int fun tzset : Void fun timegm(tp : Tm*) : TimeT diff --git a/src/lib_c/i386-linux-musl/c/time.cr b/src/lib_c/i386-linux-musl/c/time.cr index 22fdf7a86ebf..f687c8b35db4 100644 --- a/src/lib_c/i386-linux-musl/c/time.cr +++ b/src/lib_c/i386-linux-musl/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/wasm32-wasi/c/time.cr b/src/lib_c/wasm32-wasi/c/time.cr index 9d77b0f53fec..9965c3a7d324 100644 --- a/src/lib_c/wasm32-wasi/c/time.cr +++ b/src/lib_c/wasm32-wasi/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun timegm(x0 : Tm*) : TimeT fun futimes(fd : Int, times : Timeval[2]) : Int end diff --git a/src/lib_c/x86_64-darwin/c/time.cr b/src/lib_c/x86_64-darwin/c/time.cr index e20477a6a004..7e76fb969fbe 100644 --- a/src/lib_c/x86_64-darwin/c/time.cr +++ b/src/lib_c/x86_64-darwin/c/time.cr @@ -23,6 +23,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-dragonfly/c/time.cr b/src/lib_c/x86_64-dragonfly/c/time.cr index 7b7c5a3b54b7..d4f0d2111e28 100644 --- a/src/lib_c/x86_64-dragonfly/c/time.cr +++ b/src/lib_c/x86_64-dragonfly/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-freebsd/c/time.cr b/src/lib_c/x86_64-freebsd/c/time.cr index e0a72c914d82..6b84331c8361 100644 --- a/src/lib_c/x86_64-freebsd/c/time.cr +++ b/src/lib_c/x86_64-freebsd/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-linux-gnu/c/time.cr b/src/lib_c/x86_64-linux-gnu/c/time.cr index b93b8e698dd9..710d477e269b 100644 --- a/src/lib_c/x86_64-linux-gnu/c/time.cr +++ b/src/lib_c/x86_64-linux-gnu/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(timer : TimeT*, tp : Tm*) : Tm* fun localtime_r(timer : TimeT*, tp : Tm*) : Tm* fun mktime(tp : Tm*) : TimeT + fun nanosleep(req : Timespec*, rem : Timespec*) : Int fun tzset : Void fun timegm(tp : Tm*) : TimeT diff --git a/src/lib_c/x86_64-linux-musl/c/time.cr b/src/lib_c/x86_64-linux-musl/c/time.cr index 22fdf7a86ebf..f687c8b35db4 100644 --- a/src/lib_c/x86_64-linux-musl/c/time.cr +++ b/src/lib_c/x86_64-linux-musl/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-netbsd/c/time.cr b/src/lib_c/x86_64-netbsd/c/time.cr index 17fb6b2dcaa6..a0f11bb50283 100644 --- a/src/lib_c/x86_64-netbsd/c/time.cr +++ b/src/lib_c/x86_64-netbsd/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r = __gmtime_r50(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r = __localtime_r50(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime = __mktime50(x0 : Tm*) : TimeT + fun nanosleep = __nanosleep50(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm = __timegm50(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-openbsd/c/time.cr b/src/lib_c/x86_64-openbsd/c/time.cr index 704a722c2a7e..e7979bfba679 100644 --- a/src/lib_c/x86_64-openbsd/c/time.cr +++ b/src/lib_c/x86_64-openbsd/c/time.cr @@ -28,6 +28,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT diff --git a/src/lib_c/x86_64-solaris/c/time.cr b/src/lib_c/x86_64-solaris/c/time.cr index c8fc7ea9231f..531f8e373f4b 100644 --- a/src/lib_c/x86_64-solaris/c/time.cr +++ b/src/lib_c/x86_64-solaris/c/time.cr @@ -26,6 +26,7 @@ lib LibC fun gmtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun localtime_r(x0 : TimeT*, x1 : Tm*) : Tm* fun mktime(x0 : Tm*) : TimeT + fun nanosleep(x0 : Timespec*, x1 : Timespec*) : Int fun tzset : Void fun timegm(x0 : Tm*) : TimeT