summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-06-06 01:36:54 +0200
committerTyge Løvset <[email protected]>2023-06-06 01:36:54 +0200
commitf2d90c87590133547e474da4ea9d5dd1b834043e (patch)
treedde7bcfbaf2b5d4ec4a84cf8d68f6a7ccc90e6c0
parent4b8f8d2a97ca1411ad6dccdeac6195574edac852 (diff)
downloadSTC-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.md8
-rw-r--r--include/stc/algo/coroutine.h63
-rw-r--r--misc/examples/dining_philosophers.c20
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);
}