diff options
| author | Tyge Løvset <[email protected]> | 2023-06-06 01:36:54 +0200 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-06-06 01:36:54 +0200 |
| commit | f2d90c87590133547e474da4ea9d5dd1b834043e (patch) | |
| tree | dde7bcfbaf2b5d4ec4a84cf8d68f6a7ccc90e6c0 | |
| parent | 4b8f8d2a97ca1411ad6dccdeac6195574edac852 (diff) | |
| download | STC-modified-f2d90c87590133547e474da4ea9d5dd1b834043e.tar.gz STC-modified-f2d90c87590133547e474da4ea9d5dd1b834043e.zip | |
Switched to double for times in cco_timer and cco_time, etc.
Reverted to just use Sleep on win32 - same effect.
| -rw-r--r-- | docs/ccommon_api.md | 8 | ||||
| -rw-r--r-- | include/stc/algo/coroutine.h | 63 | ||||
| -rw-r--r-- | misc/examples/dining_philosophers.c | 20 |
3 files changed, 44 insertions, 47 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 6276494b..de421f2c 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -389,17 +389,17 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c | | `cco_timer` | Timer type | | | `cco_timer_await(tm)` | Await for timer to expire | | | `cco_timer_await(tm, ret)` | Await with ret for timer to expire | -| | `cco_timer_start(tm, long usec)` | Start timer for usec microseconds | +| | `cco_timer_start(tm, double sec)` | Start timer for sec seconds | | | `cco_timer_restart(tm)` | Restart timer with same duration | | `bool` | `cco_timer_expired(tm)` | Return true if timer is expired | -|`long long`| `cco_timer_remaining(tm)` | Return microseconds remaining | +| `double` | `cco_timer_remaining(tm)` | Return seconds remaining | | | From caller side: | | | `void` | `cco_stop(co)` | Next call of coroutine finalizes | | `void` | `cco_reset(co)` | Reset state to initial (for reuse) | | `void` | `cco_run(co, corocall) { }` | Run blocking until coro is done | | | Time functions: | | -|`long long`| `cco_utime(void)` | Return microseconds since Epoch | -| | `cco_usleep(long long usec)` | Sleep for microseconds | +| `double` | `cco_time(void)` | Return secs with usec prec. since Epoch | +| | `cco_sleep(double sec)` | Sleep for seconds | --- ## RAII scope macros diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index d0c9ad86..79819c55 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -135,71 +135,66 @@ typedef struct { #else #define _c_LINKC __declspec(dllimport) #endif - struct _FILETIME; struct _SECURITY_ATTRIBUTES; union _LARGE_INTEGER; + struct _FILETIME; _c_LINKC void GetSystemTimePreciseAsFileTime(struct _FILETIME*); - _c_LINKC void* CreateWaitableTimerW(struct _SECURITY_ATTRIBUTES*, int, const wchar_t*); - _c_LINKC int SetWaitableTimer(void*, const union _LARGE_INTEGER*, long, void(*)(void*, unsigned long, unsigned long), void*, int); - _c_LINKC unsigned long WaitForSingleObject(void*, unsigned long); - _c_LINKC int CloseHandle(void*); - - static inline long long cco_utime(void) { - static const long long epoch_offset = 11644473600000000LL; /* microseconds betweeen Jan 1,1601 - Jan 1,1970 */ - unsigned long long quad; /* 64-bit value, 100-nanosecond intervals since January 1, 1601 00:00 UTC */ + _c_LINKC void Sleep(unsigned long); + + static inline double cco_time(void) { + static const unsigned long long epoch_offset = 116444736000000000ULL; /* 1/10th usecs betweeen Jan 1,1601 - Jan 1,1970 */ + unsigned long long quad; /* 64-bit value, 100-nanosecond intervals since January 1, 1601 00:00 UTC */ GetSystemTimePreciseAsFileTime((struct _FILETIME*)&quad); - return (long long)quad/10 - epoch_offset; /* microseconds since epoch */ + return (double)(quad - epoch_offset)*1e-7; /* usecs since epoch */ } - static inline void cco_usleep(long long usec) { - unsigned long long ft = -10*usec; - void* timer = CreateWaitableTimerW(NULL, true, NULL); - SetWaitableTimer(timer, (const union _LARGE_INTEGER*)&ft, 0, NULL, NULL, 0); - WaitForSingleObject(timer, ~0UL); - CloseHandle(timer); - } + static inline void cco_sleep(double sec) { + Sleep((unsigned long)(sec*1000.0)); + } #else #include <sys/time.h> - static inline long long cco_utime(void) { + static inline double cco_time(void) { struct timeval tv; gettimeofday(&tv, NULL); - return tv.tv_sec*1000000LL + tv.tv_usec; + return tv.tv_sec + tv.tv_usec*1e-6; } - static inline void cco_usleep(long long usec) { - struct timeval tv = {.tv_sec=(time_t)(usec/1000000), .tv_usec=(suseconds_t)(usec % 1000000)}; + static inline void cco_sleep(double sec) { + struct timeval tv; + tv.tv_sec = (time_t)sec; + tv.tv_usec = (suseconds_t)(1e6*(sec - tv.tv_sec)); select(0, NULL, NULL, NULL, &tv); } #endif -typedef struct { long long interval, start; } cco_timer; +typedef struct { double interval, start; } cco_timer; #define cco_timer_await(...) c_MACRO_OVERLOAD(cco_timer_await, __VA_ARGS__) -#define cco_timer_await_2(tm, usec) cco_timer_await_3(tm, usec, ) -#define cco_timer_await_3(tm, usec, ret) \ +#define cco_timer_await_2(tm, sec) cco_timer_await_3(tm, sec, ) +#define cco_timer_await_3(tm, sec, ret) \ do { \ - cco_timer_start(tm, usec); \ + cco_timer_start(tm, sec); \ cco_await_2(cco_timer_expired(tm), ret); \ } while (0) -static inline void cco_timer_start(cco_timer* tm, long long usec) { - tm->interval = usec; - tm->start = cco_utime(); +static inline void cco_timer_start(cco_timer* tm, double sec) { + tm->interval = sec; + tm->start = cco_time(); } -static inline cco_timer cco_timer_from(long long usec) { - cco_timer tm = {.interval=usec, .start=cco_utime()}; +static inline cco_timer cco_timer_from(double sec) { + cco_timer tm = {.interval=sec, .start=cco_time()}; return tm; } static inline void cco_timer_restart(cco_timer* tm) { - tm->start = cco_utime(); + tm->start = cco_time(); } static inline bool cco_timer_expired(cco_timer* tm) { - return cco_utime() - tm->start >= tm->interval; + return cco_time() - tm->start >= tm->interval; } -static inline long long cco_timer_remaining(cco_timer* tm) { - return tm->start + tm->interval - cco_utime(); +static inline double cco_timer_remaining(cco_timer* tm) { + return tm->start + tm->interval - cco_time(); } #endif diff --git a/misc/examples/dining_philosophers.c b/misc/examples/dining_philosophers.c index cc6e5fd2..57fcef56 100644 --- a/misc/examples/dining_philosophers.c +++ b/misc/examples/dining_philosophers.c @@ -32,17 +32,17 @@ void philosopher(struct Philosopher* p) { cco_routine(p) { while (1) { - int duration = (int)(1000 + crand() % 2000); // 1-3 seconds - printf("Philosopher %d is thinking for %d minutes...\n", p->id, duration/100); - cco_timer_await(&p->tm, duration*1000); + double duration = 1.0 + crandf()*2.0; + printf("Philosopher %d is thinking for %.0f minutes...\n", p->id, duration*10); + cco_timer_await(&p->tm, duration); printf("Philosopher %d is hungry...\n", p->id); cco_sem_await(p->left_fork); cco_sem_await(p->right_fork); - duration = (int)(500 + crand() % 1000); - printf("Philosopher %d is eating for %d minutes...\n", p->id, duration/100); - cco_timer_await(&p->tm, duration*1000); + duration = 0.5 + crandf(); + printf("Philosopher %d is eating for %.0f minutes...\n", p->id, duration*10); + cco_timer_await(&p->tm, duration); cco_sem_release(p->left_fork); cco_sem_release(p->right_fork); @@ -84,18 +84,20 @@ void dining(struct Dining* d) } } - int main() { struct Dining dine; cco_reset(&dine); - cco_timer tm = cco_timer_from(10*1000000); // microseconds + int n=0; + cco_timer tm = cco_timer_from(10.0); // seconds csrand((uint64_t)time(NULL)); while (!cco_done(&dine)) { if (cco_timer_expired(&tm)) cco_stop(&dine); dining(&dine); - cco_usleep(100); + cco_sleep(0.001); + ++n; } + printf("n=%d\n", n); } |
