summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/ccommon_api.md9
-rw-r--r--include/stc/algo/coroutine.h27
-rw-r--r--misc/examples/dining_philosophers.c7
3 files changed, 22 insertions, 21 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 1fd8af75..930b8881 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -385,14 +385,15 @@ To resume the coroutine from where it was suspended with *cco_yield()*, simply c
| | `cco_sem_await(sem)` | Await for the semaphore count > 0 |
| | `cco_sem_await(sem, ret)` | Await with ret on the semaphore |
| `cco_sem` | `cco_sem_init(long value)` | Set semaphore value |
-| | `cco_sem_release(sem)` | Signal the semaphore |
+| | `cco_sem_release(sem)` | Signal the semaphore (count += 1) |
| | Timers: | |
| | `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, double sec)` | Start timer for sec seconds (usec prec.)|
+| | `cco_timer_await(tm, double sec)` | Await secs for timer to expire (usec prec.)|
+| | `cco_timer_await(tm, double sec, ret)`| Await secs for timer with ret value |
+| | `cco_timer_start(tm, double sec)` | Start timer for secs duration |
| | `cco_timer_restart(tm)` | Restart timer with same duration |
| `bool` | `cco_timer_expired(tm)` | Return true if timer is expired |
+| `double` | `cco_timer_elapsed(tm)` | Return seconds elapsed |
| `double` | `cco_timer_remaining(tm)` | Return seconds remaining |
| | From caller side: | |
| `void` | `cco_stop(co)` | Next call of coroutine finalizes |
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index f03fc836..81c75aa1 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -67,12 +67,12 @@ enum {
#define cco_done(co) ((co)->cco_state == cco_state_done)
#define cco_routine(co) \
- for (int *_state = &(co)->cco_state, _once=1; _once; *_state = cco_state_done, _once=0) \
- _begin: switch (*_state) case 0: // thanks, @liigo!
+ for (int *_state = &(co)->cco_state; *_state != cco_state_done; *_state = cco_state_done) \
+ _resume: switch (*_state) case 0: // thanks, @liigo!
#define cco_yield(ret) \
do { \
- *_state = __LINE__; return ret; goto _begin; \
+ *_state = __LINE__; return ret; goto _resume; \
case __LINE__:; \
} while (0)
@@ -81,7 +81,7 @@ enum {
#define cco_await_2(promise, ret) \
do { \
*_state = __LINE__; \
- case __LINE__: if (!(promise)) {return ret; goto _begin;} \
+ case __LINE__: if (!(promise)) {return ret; goto _resume;} \
} while (0)
#define cco_run(co, call) while (call, !cco_done(co))
@@ -91,13 +91,13 @@ enum {
#define cco_return \
do { \
- *_state = *_state < 0 ? cco_state_done : cco_state_final; \
- goto _begin; \
+ *_state = *_state >= 0 ? cco_state_final : cco_state_done; \
+ goto _resume; \
} while (0)
#define cco_return_v(value) \
do { \
- *_state = *_state < 0 ? cco_state_done : cco_state_final; \
+ *_state = *_state >= 0 ? cco_state_final : cco_state_done; \
return value; \
} while (0)
@@ -115,9 +115,7 @@ enum {
* Semaphore
*/
-typedef struct {
- intptr_t count;
-} cco_sem;
+typedef struct { intptr_t count; } cco_sem;
#define cco_sem_await(...) c_MACRO_OVERLOAD(cco_sem_await, __VA_ARGS__)
#define cco_sem_await_1(sem) cco_sem_await_2(sem, )
@@ -146,10 +144,9 @@ typedef struct {
_c_LINKC void Sleep(unsigned long);
static inline double cco_time(void) { /* seconds since epoch */
- 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 */
+ unsigned long long quad; /* 64-bit value representing 1/10th usecs since Jan 1 1601, 00:00 UTC */
GetSystemTimePreciseAsFileTime((struct _FILETIME*)&quad);
- return (double)(quad - epoch_offset)*1e-7;
+ return (double)(quad - 116444736000000000ULL)*1e-7; /* time diff Jan 1 1601-Jan 1 1970 in 1/10th usecs */
}
static inline void cco_sleep(double sec) {
@@ -199,6 +196,10 @@ static inline bool cco_timer_expired(cco_timer* tm) {
return cco_time() - tm->start >= tm->interval;
}
+static inline double cco_timer_elapsed(cco_timer* tm) {
+ return cco_time() - tm->start;
+}
+
static inline double cco_timer_remaining(cco_timer* tm) {
return tm->start + tm->interval - cco_time();
}
diff --git a/misc/examples/dining_philosophers.c b/misc/examples/dining_philosophers.c
index 57fcef56..f9c05e71 100644
--- a/misc/examples/dining_philosophers.c
+++ b/misc/examples/dining_philosophers.c
@@ -22,7 +22,6 @@ struct Dining {
// Define semaphores for the forks
cco_sem forks[num_forks];
struct Philosopher ph[num_philosophers];
- int ph_idx;
int cco_state; // required
};
@@ -43,7 +42,7 @@ void philosopher(struct Philosopher* p)
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);
}
@@ -69,8 +68,8 @@ void dining(struct Dining* d)
while (1) {
// per-"frame" logic update of all philosophers states
- for (d->ph_idx = 0; d->ph_idx < num_philosophers; ++d->ph_idx) {
- philosopher(&d->ph[d->ph_idx]);
+ for (int i = 0; i < num_philosophers; ++i) {
+ philosopher(&d->ph[i]);
}
cco_yield(); // suspend, return control back to main
}