From c931a3330837f62bd69f94f3552262dcc11f1096 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Mon, 21 Oct 2024 15:23:17 +0300 Subject: [PATCH] std/time: reimplement the Sleep function --- std/internal/zbits/fits.jule | 22 ++++++++++++++++++++++ std/runtime/sleep.jule | 8 ++++++++ std/runtime/sleep_unix.jule | 29 +++++++++++++++++++++++++++++ std/runtime/sleep_windows.jule | 29 +++++++++++++++++++++++++++++ std/runtime/time.jule | 26 ++++++++++++++++++++++++++ std/runtime/time_unix.jule | 10 ++++++++++ std/sys/time.jule | 23 +++-------------------- std/time/duration.jule | 26 +++++++++++++++++++------- std/time/thread.jule | 25 ------------------------- 9 files changed, 146 insertions(+), 52 deletions(-) create mode 100644 std/internal/zbits/fits.jule create mode 100644 std/runtime/sleep.jule create mode 100644 std/runtime/sleep_unix.jule create mode 100644 std/runtime/sleep_windows.jule create mode 100644 std/runtime/time.jule create mode 100644 std/runtime/time_unix.jule delete mode 100644 std/time/thread.jule diff --git a/std/internal/zbits/fits.jule b/std/internal/zbits/fits.jule new file mode 100644 index 000000000..5e985cabe --- /dev/null +++ b/std/internal/zbits/fits.jule @@ -0,0 +1,22 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +// Reports whether n fits in bits. +fn Fits(n: i64, bits: uint): bool { + const MaxBits = 64 + if bits < MaxBits { + if n < 0 { + limit := i64(-1) << (bits - 1) + if n < limit { + ret false + } + } else { + limit := i64(1)<<(bits-1) - 1 + if n > limit { + ret false + } + } + } + ret true +} \ No newline at end of file diff --git a/std/runtime/sleep.jule b/std/runtime/sleep.jule new file mode 100644 index 000000000..d291b4b5f --- /dev/null +++ b/std/runtime/sleep.jule @@ -0,0 +1,8 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +type sleepDuration: i64 + +// See documentation of the `time::Sleep` function. +fn sleep(dur: sleepDuration) { _sleep(dur) } \ No newline at end of file diff --git a/std/runtime/sleep_unix.jule b/std/runtime/sleep_unix.jule new file mode 100644 index 000000000..feab3482b --- /dev/null +++ b/std/runtime/sleep_unix.jule @@ -0,0 +1,29 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use "std/internal/zbits" +use "std/mem" + +cpp unsafe fn nanosleep(*cpp.timespec, *cpp.timespec): int + +// See documentation of the sleep function. +fn _sleep(dur: sleepDuration) { + mut sec := dur / _Second + nsec := dur % _Second // always fits in timespec.tv_nsec + + mut req := cpp.timespec{} + secBits := mem::SizeOf(req.tv_sec) * 8 + limit := i64(1)<<(secBits-1) - 1 + for ; sec -= limit { + if sec <= limit { + req.tv_sec = sec + req.tv_nsec = nsec + unsafe { cpp.nanosleep(&req, nil) } + break + } else { + req.tv_sec = limit + unsafe { cpp.nanosleep(&req, nil) } + } + } +} \ No newline at end of file diff --git a/std/runtime/sleep_windows.jule b/std/runtime/sleep_windows.jule new file mode 100644 index 000000000..73821413a --- /dev/null +++ b/std/runtime/sleep_windows.jule @@ -0,0 +1,29 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use "std/internal/zbits" + +type _DWORD: u32 + +cpp fn Sleep(_DWORD) + +// See documentation of the sleep function. +fn _sleep(dur: sleepDuration) { + mut ms := dur / _Millisecond + if ms == 0 { + // Less than a millisecond, Windows's Sleep function have no precision <1ms. + // To make guaranteed at least given duration is elapsed, sleep for a millisecond. + ms = 1 + } + const dwordBits = 32 + limit := i64(1) << (dwordBits) + for ; ms -= limit { + if ms <= limit { + cpp.Sleep(unsafe { _DWORD(ms) }) + break + } else { + cpp.Sleep(unsafe { _DWORD(limit) }) + } + } +} \ No newline at end of file diff --git a/std/runtime/time.jule b/std/runtime/time.jule new file mode 100644 index 000000000..1357593ac --- /dev/null +++ b/std/runtime/time.jule @@ -0,0 +1,26 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +// A nanosecond. +const _Nanosecond = 1 + +// Nanoseconds in microsecond. +// How many nanoseconds are in microsecond. +const _Microsecond = 1000 * _Nanosecond + +// Nanoseconds in millisecond. +// How many nanoseconds are in millisecond. +const _Millisecond = 1000 * _Microsecond + +// Nanoseconds in second. +// How many nanoseconds are in second. +const _Second = 1000 * _Millisecond + +// Nanoseconds in minute. +// How many nanoseconds are in minute. +const _Minute = 60 * _Second + +// Nanoseconds in hour. +// How many nanoseconds are in hour. +const _Hour = 60 * _Minute \ No newline at end of file diff --git a/std/runtime/time_unix.jule b/std/runtime/time_unix.jule new file mode 100644 index 000000000..26f3a8be3 --- /dev/null +++ b/std/runtime/time_unix.jule @@ -0,0 +1,10 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +cpp use "" + +cpp struct timespec { + tv_sec: i64 + tv_nsec: i64 +} \ No newline at end of file diff --git a/std/sys/time.jule b/std/sys/time.jule index 3bd83c9a5..53af8abcb 100644 --- a/std/sys/time.jule +++ b/std/sys/time.jule @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD 3-Clause // license that can be found in the LICENSE file. +use "std/internal/zbits" use "std/mem" #typedef @@ -13,33 +14,15 @@ cpp struct timeval { // C's timeval structure. type Timeval: cpp.timeval -fn checkBits(n: i64, bits: uint): bool { - const maxBits = 64 - if bits < maxBits { - if n < 0 { - limit := i64(-1) << (bits - 1) - if n < limit { - ret false - } - } else { - limit := i64(1)<<(bits-1) - 1 - if n > limit { - ret false - } - } - } - ret true -} - // Creates new Timeval by sec and usec. // Sets fields of the out. // Reports whether sec and usec have valid range. // If sec or usec have invalid range, out will not be mutated. fn NewTimeval(sec: i64, usec: i64, mut &out: Timeval): bool { - if !checkBits(sec, mem::SizeOf(out.tv_sec)*8) { + if !zbits::Fits(sec, mem::SizeOf(out.tv_sec)*8) { ret false } - if !checkBits(usec, mem::SizeOf(out.tv_usec)*8) { + if !zbits::Fits(usec, mem::SizeOf(out.tv_usec)*8) { ret false } out.tv_sec = unsafe { (secType)(sec) } diff --git a/std/time/duration.jule b/std/time/duration.jule index 8555c4e44..b3df537a9 100644 --- a/std/time/duration.jule +++ b/std/time/duration.jule @@ -2,8 +2,20 @@ // Use of this source code is governed by a BSD 3-Clause // license that can be found in the LICENSE file. +use "std/runtime" + // Integer type of durations. -type DurInt: i64 +type DurInt: runtime::sleepDuration + +// Stops execution of the caller thread by stated duration. +// This function only affects execution of caller thread, not process. +// If duration is <=0, function will return immediately. +// It guarantees sleeping at least for the stated duration. +fn Sleep(mut dur: DurInt) { + if dur >= 0 { + runtime::sleep(dur) + } +} // Duration is the time between two times. struct Duration{} @@ -13,27 +25,27 @@ impl Duration { const max = DurInt.Max // A nanosecond. - const Nanosecond: DurInt = 1 + const Nanosecond: DurInt = runtime::_Nanosecond // Nanoseconds in microsecond. // How many nanoseconds are in microsecond. - const Microsecond: DurInt = 1000 * Duration.Nanosecond + const Microsecond: DurInt = runtime::_Microsecond // Nanoseconds in millisecond. // How many nanoseconds are in millisecond. - const Millisecond: DurInt = 1000 * Duration.Microsecond + const Millisecond: DurInt = runtime::_Millisecond // Nanoseconds in second. // How many nanoseconds are in second. - const Second: DurInt = 1000 * Duration.Millisecond + const Second: DurInt = runtime::_Second // Nanoseconds in minute. // How many nanoseconds are in minute. - const Minute: DurInt = 60 * Duration.Second + const Minute: DurInt = runtime::_Minute // Nanoseconds in hour. // How many nanoseconds are in hour. - const Hour: DurInt = 60 * Duration.Minute + const Hour: DurInt = runtime::_Hour // Returns duration as nanoseconds. static fn Nanoseconds(d: DurInt): DurInt { diff --git a/std/time/thread.jule b/std/time/thread.jule deleted file mode 100644 index 347ea8edf..000000000 --- a/std/time/thread.jule +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -cpp use "" - -// Safe mask for std::chrono::nanoseconds type. -// Used for avoid implicit casting for numeric types. -cpp type chrono_ns: u64 - -// Safe mask for std::chrono::nanoseconds type. -// Used for casting. -#namespace "std::chrono" -cpp fn nanoseconds(ns: u64): cpp.chrono_ns - -#namespace "std::this_thread" -cpp fn sleep_for(x: cpp.chrono_ns) - -// Stops execution of caller thread by absolute duration. -// This function only affects execution of caller thread, not process. -fn Sleep(mut dur: DurInt) { - dur = Duration.Abs(dur) - ns := u64(Duration.Nanoseconds(dur)) - cpp.sleep_for(cpp.nanoseconds(ns)) -} \ No newline at end of file