hoshi-lang dev
Yet another programming language
Loading...
Searching...
No Matches
time.cpp
Go to the documentation of this file.
1#include <ctime>
2#include <runtime/time/time.h>
4
5#include <stdio.h>
6
7#if defined (_WIN32)
8
9long get_tm_gmtoff(struct tm *t) {
10 struct tm temp = *t;
11
12 time_t utc_timestamp = _mkgmtime(&temp);
13
14 temp = *t;
15 temp.tm_isdst = -1;
16
17 time_t local_timestamp = mktime(&temp);
18
19 return (long)(utc_timestamp - local_timestamp);
20}
21
22static struct tm *localtime_r(const time_t *timer, struct tm *buf) {
23 if (timer == NULL || buf == NULL) {
24 return NULL;
25 }
26
27 errno_t err = localtime_s(buf, timer);
28
29 if (err != 0) {
30 return NULL;
31 }
32
33 return buf;
34}
35
36static struct tm* gmtime_r(const time_t* timer, struct tm* buf) {
37 if (timer == NULL || buf == NULL) {
38 return NULL;
39 }
40
41 errno_t err = gmtime_s(buf, timer);
42
43 if (err != 0) {
44 return NULL;
45 }
46
47 return buf;
48}
49
50#if !defined (__CYGWIN__) && !defined (__MINGW32__)
51
52#include <windows.h>
53
54#define DELTA_EPOCH_IN_MICROSECS 116444736000000000LL
55
56int clock_gettime(int clk_id, struct timespec *tp) {
57 if (tp == NULL)
58 return -1;
59
60 if (clk_id == CLOCK_REALTIME) {
61 FILETIME ft;
62 GetSystemTimePreciseAsFileTime(&ft);
63
64 uint64_t t = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
65
66 t -= DELTA_EPOCH_IN_MICROSECS;
67
68 tp->tv_sec = (time_t)(t / 10000000); // 100ns to seconds
69 tp->tv_nsec = (long)((t % 10000000) * 100); // Remaining 100ns to ns
70
71 return 0;
72 } else if (clk_id == CLOCK_MONOTONIC) {
73 static LARGE_INTEGER freq = {0};
74 LARGE_INTEGER count;
75
76 // Get frequency once (it doesn't change after boot)
77 if (freq.QuadPart == 0) {
78 if (!QueryPerformanceFrequency(&freq))
79 return -1;
80 }
81
82 if (!QueryPerformanceCounter(&count))
83 return -1;
84
85 // Convert QPC units to seconds and nanoseconds
86 tp->tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
87
88 // Calculate remainder carefully to avoid overflow before division
89 // logic: (count % freq) * 1e9 / freq
90 tp->tv_nsec = (long)(((count.QuadPart % freq.QuadPart) * 1000000000) / freq.QuadPart);
91
92 return 0;
93 }
94
95 return -1; // Unknown clock ID
96}
97
98int nanosleep(const struct timespec *req, struct timespec *rem) {
99 if (req == NULL || req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000) {
100 return -1;
101 }
102
103 // Windows WaitableTimers use 100-nanosecond intervals.
104 // Negative value indicates relative time.
105 LARGE_INTEGER li;
106
107 // Convert seconds + nanoseconds to 100ns ticks
108 int64_t interval = req->tv_sec * 10000000LL + req->tv_nsec / 100;
109 li.QuadPart = -interval;
110
111// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION requires Win 10 build 1803 or later.
112// If running on older Windows, fallback to 0 (standard resolution).
113#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
114#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
115#endif
116
117 HANDLE timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
118
119 if (!timer) {
120 // Fallback for Win7/8 if Ex fails or flag unsupported
121 timer = CreateWaitableTimer(NULL, TRUE, NULL);
122 if (!timer)
123 return -1;
124 }
125
126 if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) {
127 CloseHandle(timer);
128 return -1;
129 }
130
131 // Wait for the timer
132 WaitForSingleObject(timer, INFINITE);
133 CloseHandle(timer);
134
135 // Note: Windows handles interruptions (APCs) differently than POSIX signals.
136 // In a strict port, you would check if WaitForSingleObject returns WAIT_IO_COMPLETION
137 // and calculate 'rem'. For most uses, this is unnecessary complexity.
138 if (rem) {
139 rem->tv_sec = 0;
140 rem->tv_nsec = 0;
141 }
142
143 return 0;
144}
145#endif // !defined (__CYGWIN__) && !defined (__MINGW32__)
146
147#else
148
149long get_tm_gmtoff(struct tm *t) {
150 return t->tm_gmtoff;
151}
152
153#endif // _WIN32
154
161
162YoiIntAndIntObject *YoiIntAndIntObject::create(int64_t seconds, int64_t nanoseconds) {
164 obj->gc_refcount = 1;
165 obj->type_id = 0;
166 obj->seconds = seconds;
167 obj->nanoseconds = nanoseconds;
168 obj->weak_slots_head = nullptr;
169 return obj;
170}
171
173 struct timespec ts{};
174 clock_gettime(CLOCK_REALTIME, &ts);
175 int64_t seconds = ts.tv_sec;
176 int64_t nanoseconds = ts.tv_nsec;
177 return YoiIntAndIntObject::create(seconds, nanoseconds);
178}
179
180void runtime_time_sleep(int64_t seconds, int64_t nanoseconds) {
181 struct timespec ts{};
182 ts.tv_sec = seconds;
183 ts.tv_nsec = nanoseconds;
184 nanosleep(&ts, nullptr);
185}
186
187char *runtime_time_strftime(const char *format, int64_t timestamp) {
188 time_t t = timestamp;
189 struct tm tm{};
190 gmtime_r(&t, &tm);
191 char *result = (char *)malloc(MAX_TIME_STR_LEN);
192 strftime(result, MAX_TIME_STR_LEN, format, &tm);
193 return result;
194}
195
197 time_t now = time(nullptr);
198 tm local_time{};
199 localtime_r(&now, &local_time);
200 return get_tm_gmtoff(&local_time);
201}
202
204 struct timespec ts{};
205 clock_gettime(CLOCK_MONOTONIC, &ts);
206 int64_t seconds = ts.tv_sec;
207 int64_t nanoseconds = ts.tv_nsec;
208 return YoiIntAndIntObject::create(seconds, nanoseconds);
209}
210
211void runtime_time_finalize(void *memory) {
212 free(memory);
213}
void * runtime_object_alloc(unsigned long size)
Definition memory.cpp:96
void runtime_finalize_object(YoiObject *object)
Definition memory.cpp:90
unsigned long long gc_refcount
Definition time.h:24
unsigned long long seconds
Definition time.h:26
void * weak_slots_head
Definition time.h:28
unsigned long long nanoseconds
Definition time.h:27
static void gc_refcount_decrease(YoiIntAndIntObject *obj)
Definition time.cpp:155
static YoiIntAndIntObject * create(int64_t seconds, int64_t nanoseconds)
Definition time.cpp:162
int64_t runtime_time_localtimezone_offset()
Get the local timezone offset in seconds.
Definition time.cpp:196
long get_tm_gmtoff(struct tm *t)
Definition time.cpp:149
YoiIntAndIntObject * runtime_time_monotonic_now()
Get the current monotonic time as a YoiIntAndIntObject.
Definition time.cpp:203
void runtime_time_sleep(int64_t seconds, int64_t nanoseconds)
Sleep for a given number of seconds.
Definition time.cpp:180
YoiIntAndIntObject * runtime_time_now()
Return the current time as a YoiIntAndIntObject.
Definition time.cpp:172
void runtime_time_finalize(void *memory)
Finalize the memory created by the time module.
Definition time.cpp:211
char * runtime_time_strftime(const char *format, int64_t timestamp)
Convert a timestamp to a string according to a given format.
Definition time.cpp:187
#define MAX_TIME_STR_LEN
Definition time.h:20
void runtime_weak_slot_nullify_all(WeakSlot **weak_slots_head_ptr)
Definition weak.cpp:30