diff --git a/lib/std/libc/libc_extra.c3 b/lib/std/libc/libc_extra.c3 new file mode 100644 index 000000000..f56dac51e --- /dev/null +++ b/lib/std/libc/libc_extra.c3 @@ -0,0 +1,22 @@ +module libc; +import std::time; + +/** + * @require self >= 0 + **/ +fn TimeSpec NanoDuration.to_timespec(self) @inline +{ + CLong ns = (CLong)(self % 1000_000_000); + Time_t sec = (Time_t)(self / 1000_000_000); + return { .s = sec, .ns = ns }; +} + +/** + * @require self >= 0 + **/ +fn TimeSpec Duration.to_timespec(self) @inline +{ + CLong ns = (CLong)(1000 * (self % time::SEC)); + Time_t sec = (Time_t)(self / time::SEC); + return { .s = sec, .ns = ns }; +} diff --git a/lib/std/net/socket.c3 b/lib/std/net/socket.c3 index 053677dbd..eda3569ad 100644 --- a/lib/std/net/socket.c3 +++ b/lib/std/net/socket.c3 @@ -54,6 +54,11 @@ struct Poll PollEvents revents; } +fn ulong! poll_ms(Poll[] polls, long timeout_ms) +{ + return poll(polls, time::ms(timeout_ms)) @inline; +} + /** * @param [inout] polls * @param timeout "duration to poll." diff --git a/lib/std/net/udp.c3 b/lib/std/net/udp.c3 index 79407ad97..30857f7c9 100644 --- a/lib/std/net/udp.c3 +++ b/lib/std/net/udp.c3 @@ -14,3 +14,15 @@ fn UdpSocket! connect_to(AddrInfo* ai, SocketOption... options) { return (UdpSocket)net::connect_from_addrinfo(ai, options); } + +fn UdpSocket! connect_async(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED) +{ + AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_DGRAM)!; + defer os::freeaddrinfo(ai); + return connect_async_to(ai, ...options); +} + +fn UdpSocket! connect_async_to(AddrInfo* ai, SocketOption... options) +{ + return (UdpSocket)net::connect_async_from_addrinfo(ai, options); +} diff --git a/lib/std/os/win32/process.c3 b/lib/std/os/win32/process.c3 index 0840c29aa..f9912c057 100644 --- a/lib/std/os/win32/process.c3 +++ b/lib/std/os/win32/process.c3 @@ -43,7 +43,7 @@ extern fn uint waitForMultipleObjects(uint count, Win32_HANDLE* handles, bool wa extern fn Win32_BOOL resetEvent(Win32_HANDLE event) @extern("ResetEvent"); extern fn Win32_BOOL setEvent(Win32_HANDLE handle) @extern("SetEvent"); extern fn long interlockedCompareExchange(int* dest, int exchange, int comperand) @extern("InterlockedCompareExchange"); -extern fn uint sleepEx(uint ms, bool alertable) @extern("SleepEx"); +extern fn Win32_DWORD sleepEx(Win32_DWORD ms, Win32_BOOL alertable) @extern("SleepEx"); extern fn Win32_HANDLE createThread(void* attributes, usz stack, ThreadFn func, void* arg, uint flags, uint* thread_id) @extern("CreateThread"); extern fn Win32_BOOL getExitCodeThread(Win32_HANDLE handle, uint* exit_code) @extern("GetExitCodeThread"); extern fn Win32_BOOL getExitCodeProcess(Win32_HANDLE hProcess, Win32_LPDWORD lpExitCode) @extern("GetExitCodeProcess"); diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index d780aecae..5570d9a72 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -191,22 +191,9 @@ struct PosixThreadData @private void* arg; } -fn void! native_sleep_nano(ulong nano) +fn void! native_sleep_nano(NanoDuration nano) { - TimeSpec to = { .s = 0, .ns = (CLong)nano }; - if (libc::nanosleep(&to, null)) return ThreadFault.INTERRUPTED?; -} - -fn void! native_sleep_ms(ulong ms) -{ - TimeSpec to = { .s = (Time_t)(ms / 1000), .ns = (CLong)((ms % 1000) * 1000_000) }; - if (libc::nanosleep(&to, null)) return ThreadFault.INTERRUPTED?; -} - -fn void! native_sleep(double s) -{ - Time_t si = (Time_t)s; - TimeSpec to = { .s = si, .ns = (CLong)((s - si) * 1000_000_000) }; - if (libc::nanosleep(&to, null)) return ThreadFault.INTERRUPTED?; + if (nano <= 0) return; + if (libc::nanosleep(&&nano.to_timespec(), null)) return ThreadFault.INTERRUPTED?; } diff --git a/lib/std/threads/os/thread_win32.c3 b/lib/std/threads/os/thread_win32.c3 index 7339411a4..19ce1d529 100644 --- a/lib/std/threads/os/thread_win32.c3 +++ b/lib/std/threads/os/thread_win32.c3 @@ -317,20 +317,10 @@ fn bool NativeThread.equals(thread, NativeThread other) return win32::getThreadId(thread) == win32::getThreadId(other); } -/** - * @require ms < uint.max "Too long sleep" - **/ -fn void! native_sleep_ms(ulong ms) +fn void! native_sleep_nano(NanoDuration ns) { - if (win32::sleepEx((uint)ms, true) == win32::WAIT_IO_COMPLETION) return ThreadFault.INTERRUPTED?; -} - -fn void! native_sleep(double s) -{ - return native_sleep_ms((uint)s * 1000); -} - -fn void! native_sleep_nano(ulong ns) -{ - return native_sleep_ms(ns < 1000_000 ? 1 : ns / 1000_000); + long ms = ns.to_ms(); + if (ms <= 0) return; + if (ms > Win32_DWORD.max) ms = Win32_DWORD.max; + if (win32::sleepEx((Win32_DWORD)ms, (Win32_BOOL)true) == win32::WAIT_IO_COMPLETION) return ThreadFault.INTERRUPTED?; } diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index 9bee4ab4a..7309f272a 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -68,6 +68,6 @@ macro void OnceFlag.call(&flag, OnceFn func) => NativeOnceFlag.call_once((Native macro void yield() => os::native_thread_yield(); macro Thread current() => os::native_thread_current(); macro void exit(int result) => os::native_thread_exit(result); -macro void! sleep(double s) @maydiscard => os::native_sleep(s); -macro void! sleep_ms(ulong ms) @maydiscard => os::native_sleep_ms(ms); -macro void! sleep_ns(ulong ns) @maydiscard => os::native_sleep_nano(ns); +macro void! sleep(Duration d) @maydiscard => os::native_sleep_nano(d.to_nano()); +macro void! sleep_ms(ulong ms) @maydiscard => sleep(time::ms(ms)); +macro void! sleep_ns(NanoDuration ns) @maydiscard => os::native_sleep_nano(ns); diff --git a/lib/std/time/datetime.c3 b/lib/std/time/datetime.c3 index c4057b9fb..1eb9b84ec 100644 --- a/lib/std/time/datetime.c3 +++ b/lib/std/time/datetime.c3 @@ -26,7 +26,7 @@ fn TzDateTime DateTime.to_local(&self) Time_t time_t = (Time_t)self.time.to_seconds(); libc::localtime_r(&time_t, &tm); TzDateTime dt; - dt.usec = (int)((long)self.time % (long)time::MICROSECONDS_PER_SECOND); + dt.usec = (int)((long)self.time % (long)time::SEC); dt.sec = (char)tm.tm_sec; dt.min = (char)tm.tm_min; dt.hour = (char)tm.tm_hour; @@ -64,7 +64,7 @@ fn void DateTime.set_date(&self, int year, Month month = JANUARY, int day = 1, i tm.tm_mday = day; tm.tm_year = year - 1900; Time_t time = libc::timegm(&tm); - self.set_time((Time)(time * (long)time::MICROSECONDS_PER_SECOND + us)); + self.set_time((Time)(time * (long)time::SEC + us)); } fn void DateTime.set_time(&self, Time time) @@ -72,7 +72,7 @@ fn void DateTime.set_time(&self, Time time) Tm tm @noinit; Time_t time_t = (Time_t)time.to_seconds(); libc::gmtime_r(&time_t, &tm); - self.usec = (int)((long)time % (long)time::MICROSECONDS_PER_SECOND); + self.usec = (int)((long)time % (long)time::SEC); self.sec = (char)tm.tm_sec; self.min = (char)tm.tm_min; self.hour = (char)tm.tm_hour; @@ -162,7 +162,7 @@ fn int DateTime.diff_years(&self, DateTime from) fn double DateTime.diff_sec(self, DateTime from) { - return (double)self.time.diff_us(from.time) / (double)time::MICROSECONDS_PER_SECOND; + return (double)self.time.diff_us(from.time) / (double)time::SEC; } fn Duration DateTime.diff_us(self, DateTime from) { diff --git a/lib/std/time/time.c3 b/lib/std/time/time.c3 index 91c046dbf..af0493bd1 100644 --- a/lib/std/time/time.c3 +++ b/lib/std/time/time.c3 @@ -5,16 +5,20 @@ def Duration = distinct long @inline; def Clock = distinct ulong @inline; def NanoDuration = distinct long @inline; -fn Duration ms(long l) @inline => (Duration)l * 1000; -fn Duration sec(long l) @inline => (Duration)l * MICROSECONDS_PER_SECOND; -fn Duration min(long l) @inline => (Duration)l * MICROSECONDS_PER_MINUTE; -fn Duration hour(long l) @inline => (Duration)l * MICROSECONDS_PER_HOUR; +const Duration MS = 1_000; +const Duration SEC = 1_000_000; +const Duration MIN = 60 * SEC; +const Duration HOUR = 60 * MIN; +const Duration DAY = 24 * HOUR; +const Duration WEEK = 7 * DAY; +const Duration MONTH = 30 * WEEK; +const Duration YEAR = 36525 * DAY / 100; -const Duration MICROSECONDS_PER_SECOND = 1_000_000; -const Duration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60; -const Duration MICROSECONDS_PER_HOUR = MICROSECONDS_PER_MINUTE * 60; -const Duration MICROSECONDS_PER_DAY = MICROSECONDS_PER_HOUR * 24; -const Duration MICROSECONDS_PER_WEEK = MICROSECONDS_PER_DAY * 7; +fn Duration ms(long l) @inline => (Duration)l * MS; +fn Duration sec(long l) @inline => (Duration)l * SEC; +fn Duration min(long l) @inline => (Duration)l * MIN; +fn Duration hour(long l) @inline => (Duration)l * HOUR; +fn Duration from_float(double s) @inline => (Duration)(s * SEC); struct DateTime { @@ -73,18 +77,19 @@ fn Time now() $endif } -fn Time Time.add_seconds(time, long seconds) => time + (Time)(seconds * (long)MICROSECONDS_PER_SECOND); -fn Time Time.add_minutes(time, long minutes) => time + (Time)(minutes * (long)MICROSECONDS_PER_MINUTE); -fn Time Time.add_hours(time, long hours) => time + (Time)(hours * (long)MICROSECONDS_PER_HOUR); -fn Time Time.add_days(time, long days) => time + (Time)(days * (long)MICROSECONDS_PER_DAY); -fn Time Time.add_weeks(time, long weeks) => time + (Time)(weeks * (long)MICROSECONDS_PER_WEEK); -fn double Time.to_seconds(time) => (long)time / (double)MICROSECONDS_PER_SECOND; +fn Time Time.add_seconds(time, long seconds) => time + (Time)(seconds * (long)MS); +fn Time Time.add_minutes(time, long minutes) => time + (Time)(minutes * (long)MIN); +fn Time Time.add_hours(time, long hours) => time + (Time)(hours * (long)HOUR); +fn Time Time.add_days(time, long days) => time + (Time)(days * (long)DAY); +fn Time Time.add_weeks(time, long weeks) => time + (Time)(weeks * (long)WEEK); +fn Time Time.add_duration(time, Duration duration) => time + (Time)duration; +fn double Time.to_seconds(time) => (long)time / (double)SEC; fn Duration Time.diff_us(time, Time other) => (Duration)(time - other); -fn double Time.diff_sec(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_SECOND; -fn double Time.diff_min(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_MINUTE; -fn double Time.diff_hour(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_HOUR; -fn double Time.diff_days(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_DAY; -fn double Time.diff_weeks(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_WEEK; +fn double Time.diff_sec(time, Time other) => (long)time.diff_us(other) / (double)SEC; +fn double Time.diff_min(time, Time other) => (long)time.diff_us(other) / (double)MIN; +fn double Time.diff_hour(time, Time other) => (long)time.diff_us(other) / (double)HOUR; +fn double Time.diff_days(time, Time other) => (long)time.diff_us(other) / (double)DAY; +fn double Time.diff_weeks(time, Time other) => (long)time.diff_us(other) / (double)WEEK; fn double NanoDuration.to_sec(nd) => (double)nd / 1_000_000_000.0; fn long NanoDuration.to_ms(nd) => (long)nd / 1_000_000; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 46b1d5cc8..6b03367df 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6993,7 +6993,6 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) Expr *main_var = expr->ct_call_expr.main_var; Decl *decl = sema_expr_analyse_var_path(context, main_var); if (!decl) return false; - Type *type = decl->type; TokenType name_type = expr->ct_call_expr.token_type;