summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-05-08 07:40:41 +0200
committerTyge Løvset <[email protected]>2023-05-08 07:40:41 +0200
commitbca31bb8d85d6781f0c3d074eb1a25fa6de48e07 (patch)
treee4938ea3acf08bcdd31f003c1e83f9b1ab29e0dc
parentb03148caa1d6fc660e6e7c5986dd6fd38779bedc (diff)
downloadSTC-modified-bca31bb8d85d6781f0c3d074eb1a25fa6de48e07.tar.gz
STC-modified-bca31bb8d85d6781f0c3d074eb1a25fa6de48e07.zip
Updated API for timer and semaphores in coroutine.h (ctimer, csem)
-rw-r--r--docs/ccommon_api.md17
-rw-r--r--include/stc/algo/coroutine.h68
2 files changed, 66 insertions, 19 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 2319109b..c20043f8 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -362,12 +362,21 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | `cco_yield()` | Suspend execution |
| | `cco_yield(retval)` | Suspend execution and return retval |
| | `cco_await(promise)` | Suspend until promise is true |
-| | `cco_await_with(promise, retval)` | Suspend with retval until promise is true |
+| | `cco_await(promise, retval)` | Suspend with retval until promise is true |
| | Semaphores: | |
-| | `cco_semaphore` | Semaphore type |
+| | `csem` | Semaphore type |
| | `cco_await_sem(sem)` | Await for the semaphore count > 0 |
-| | `cco_await_sem_with(sem, retval)` | Await with retval for the semaphore |
-| | `cco_signal_sem(sem)` | Signal the semaphore by increasing count|
+| | `cco_await_sem(sem, retval)` | Await with retval for the semaphore |
+| | `csem_set(sem, long value)` | Set semaphore |
+| | `csem_signal(sem)` | Signal the semaphore |
+| | Timers: | |
+| | `ctimer` | Timer type |
+| | `cco_await_timer(tm)` | Await for timer to expire |
+| | `cco_await_timer(tm, retval)` | Await with retval for timer to expire |
+| | `ctimer_start(tm, long msecs)` | Start timer for milliseconds |
+| | `ctimer_restart(tm)` | Restart timer with same duration |
+| `bool` | `ctimer_expired(tm)` | Return true if timer is expired |
+| `long` | `ctimer_remaining(tm)` | Return milliseconds remaining |
| | From caller side: | |
| `void` | `cco_stop(ctx)` | Next call of coroutine returns `cco_end()` |
| `void` | `cco_reset(ctx)` | Reset state to initial (for reuse) |
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index c9cb8fc0..80b96bbd 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -108,17 +108,14 @@ enum {
if (*_state == cco_state_done) *_state = 0; \
} while (0)
+/*
+ * Semaphore
+ */
typedef struct {
intptr_t count;
-} cco_semaphore;
+} csem;
-/**
- * Wait for a semaphore
- *
- * This macro carries out the "wait" operation on the semaphore,
- * and causes the "thread" to block while the counter is zero.
- */
#define cco_await_sem(...) c_MACRO_OVERLOAD(cco_await_sem, __VA_ARGS__)
#define cco_await_sem_1(sem) cco_await_sem_2(sem, )
#define cco_await_sem_2(sem, retval) \
@@ -127,14 +124,55 @@ typedef struct {
--(sem)->count; \
} while (0)
-/**
- * Signal a semaphore
- *
- * This macro carries out the "signal" operation on the semaphore,
- * and increments the counter inside the semaphore, which
- * eventually will cause waiting "threads" to continue executing.
+#define csem_signal(sem) ++(sem)->count
+#define csem_set(sem, value) ((sem)->count = (value))
+
+/*
+ * Timer
*/
-#define cco_signal_sem(sem) ++(sem)->count
-#define cco_reset_sem(sem, value) ((sem)->count = (value))
+
+#include <time.h>
+
+#ifdef _WIN32
+ static inline void csleep_ms(long msecs) {
+ extern void Sleep(unsigned long);
+ Sleep((unsigned long)msecs);
+ }
+#elif _POSIX_C_SOURCE >= 199309L
+ static inline void csleep_ms(long msecs) {
+ struct timespec ts = {msecs/1000, 1000000*(msecs % 1000)};
+ nanosleep(&ts, NULL);
+ }
+#endif
+
+typedef struct {
+ clock_t start;
+ clock_t interval;
+} ctimer;
+
+#define cco_await_timer(...) c_MACRO_OVERLOAD(cco_await_timer, __VA_ARGS__)
+#define cco_await_timer_2(t, msecs) cco_await_timer_3(t, msecs, )
+#define cco_await_timer_3(t, msecs, ret) \
+ do { \
+ ctimer_start(t, msecs); \
+ cco_await_2(ctimer_expired(t), ret); \
+ } while (0)
+
+static inline void ctimer_start(ctimer* t, long msecs) {
+ t->interval = msecs*(CLOCKS_PER_SEC/1000);
+ t->start = clock();
+}
+
+static inline void ctimer_restart(ctimer* t) {
+ t->start = clock();
+}
+
+static inline bool ctimer_expired(ctimer* t) {
+ return clock() - t->start >= t->interval;
+}
+
+static inline long ctimer_remaining(ctimer* t) {
+ return (long)((double)(t->start + t->interval - clock())*(1000.0/CLOCKS_PER_SEC));
+}
#endif