summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-07-02 22:01:46 +0200
committerTyge Løvset <[email protected]>2023-07-02 23:18:10 +0200
commite25dec033773ab713a7593a923e2c83745be0b9a (patch)
tree174c9edfee09fb90b18ac17661cc9a8f291fa83c /include
parentfc43b14f706f22e3933b3d225819ea68f7ce2679 (diff)
downloadSTC-modified-e25dec033773ab713a7593a923e2c83745be0b9a.tar.gz
STC-modified-e25dec033773ab713a7593a923e2c83745be0b9a.zip
Update in coroutine API. cco_yield, cco_await, cco_await_on, cco_block_on has changed. cco_final: renamed => cco_cleanup:
Reverted i_retain template param back to => i_more.
Diffstat (limited to 'include')
-rw-r--r--include/stc/algo/coroutine.h120
-rw-r--r--include/stc/algo/sort.h2
-rw-r--r--include/stc/cdeq.h6
-rw-r--r--include/stc/priv/template2.h4
4 files changed, 77 insertions, 55 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index e20fd8ad..198b0439 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -32,22 +32,22 @@ struct iterpair {
int cco_state; // required member
};
-bool iterpair(struct iterpair* I) {
+int iterpair(struct iterpair* I) {
cco_routine(I) {
for (I->x = 0; I->x < I->max_x; I->x++)
for (I->y = 0; I->y < I->max_y; I->y++)
- cco_yield(false);
+ cco_yield();
- cco_final: // required if there is cleanup code
+ cco_cleanup: // required if there is cleanup code
puts("final");
}
- return true; // finished
+ return 0; // CCO_DONE
}
int main(void) {
struct iterpair it = {.max_x=3, .max_y=3};
int n = 0;
- while (!iterpair(&it))
+ while (iterpair(&it))
{
printf("%d %d\n", it.x, it.y);
// example of early stop:
@@ -59,12 +59,19 @@ int main(void) {
#include "../ccommon.h"
enum {
- cco_state_final = -1,
- cco_state_done = -2,
+ CCO_STATE_CLEANUP = -1,
+ CCO_STATE_DONE = -2,
};
+typedef enum {
+ CCO_DONE = 0,
+ CCO_YIELD = 1,
+ CCO_AWAIT = 2,
+ CCO_ERROR = -1,
+} cco_result;
#define cco_initial(co) ((co)->cco_state == 0)
-#define cco_done(co) ((co)->cco_state == cco_state_done)
+#define cco_suspended(co) ((co)->cco_state > 0)
+#define cco_done(co) ((co)->cco_state == CCO_STATE_DONE)
/* Emulate switch in coro: always use { } after cco_case(val) and cco_default. */
#define cco_switch(x) for (long long _sw = (long long)(x), _b=0; !_b; _b=1)
@@ -72,83 +79,97 @@ enum {
#define cco_default
#define cco_routine(co) \
- for (int *_state = &(co)->cco_state; *_state != cco_state_done; *_state = cco_state_done) \
+ 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) \
+#define cco_yield() cco_yield_v(CCO_YIELD)
+#define cco_yield_v(ret) \
do { \
*_state = __LINE__; return ret; goto _resume; \
case __LINE__:; \
} while (0)
-#define cco_await(...) c_MACRO_OVERLOAD(cco_await, __VA_ARGS__)
-#define cco_await_1(promise) cco_await_2(promise, )
-#define cco_await_2(promise, ret) \
+#define cco_await(promise) cco_await_v_2(promise, CCO_AWAIT)
+#define cco_await_v(...) c_MACRO_OVERLOAD(cco_await_v, __VA_ARGS__)
+#define cco_await_v_1(promise) cco_await_v_2(promise, )
+#define cco_await_v_2(promise, ret) \
do { \
*_state = __LINE__; \
case __LINE__: if (!(promise)) {return ret; goto _resume;} \
} while (0)
-#define cco_closure(Ret, Closure, ...) \
- struct Closure { \
- Ret (*cco_fn)(struct Closure*); \
- int cco_state; \
- __VA_ARGS__ \
- }
-
-typedef struct cco_base {
- void (*cco_fn)(struct cco_base*);
- int cco_state;
-} cco_base;
-
-#define cco_base_cast(closure) \
- ((cco_base *)(closure) + 0*sizeof((cco_resume(closure), (int*)0 == &(closure)->cco_state)))
-
-#define cco_resume(closure) (closure)->cco_fn(closure)
-#define cco_await_on(...) c_MACRO_OVERLOAD(cco_await_on, __VA_ARGS__)
-#define cco_await_on_1(closure) cco_await_2((cco_resume(closure), cco_done(closure)), )
-#define cco_await_on_2(co, func) cco_await_2((func(co), cco_done(co)), )
+/* cco_await_on(): assumes coroutine returns a cco_result value (int) */
+#define cco_await_on(corocall) \
+ do { \
+ *_state = __LINE__; \
+ case __LINE__: { int _r = corocall; if (_r != CCO_DONE) {return _r; goto _resume;} } \
+ } while (0)
+/* cco_block_on(): assumes coroutine returns a cco_result value (int) */
#define cco_block_on(...) c_MACRO_OVERLOAD(cco_block_on, __VA_ARGS__)
-#define cco_block_on_1(closure) while (cco_resume(closure), !cco_done(closure))
-#define cco_block_on_2(co, func) while (func(co), !cco_done(co))
+#define cco_block_on_1(corocall) while (corocall != CCO_DONE)
+#define cco_block_on_2(corocall, res) while ((*(res) = (corocall)) != CCO_DONE)
-#define cco_final \
- *_state = cco_state_final; case cco_state_final
+#define cco_cleanup \
+ *_state = CCO_STATE_CLEANUP; case CCO_STATE_CLEANUP
#define cco_return \
do { \
- *_state = *_state >= 0 ? cco_state_final : cco_state_done; \
+ *_state = *_state >= 0 ? CCO_STATE_CLEANUP : CCO_STATE_DONE; \
goto _resume; \
} while (0)
-#define cco_return_v(value) \
+#define cco_yield_final() cco_yield_final_v(CCO_YIELD)
+#define cco_yield_final_v(value) \
do { \
- *_state = *_state >= 0 ? cco_state_final : cco_state_done; \
+ *_state = *_state >= 0 ? CCO_STATE_CLEANUP : CCO_STATE_DONE; \
return value; \
} while (0)
#define cco_stop(co) \
do { \
int* _s = &(co)->cco_state; \
- if (*_s > 0) *_s = cco_state_final; \
- else if (*_s == 0) *_s = cco_state_done; \
+ if (*_s > 0) *_s = CCO_STATE_CLEANUP; \
+ else if (*_s == 0) *_s = CCO_STATE_DONE; \
} while (0)
#define cco_reset(co) \
(void)((co)->cco_state = 0)
/*
+ * Closure (optional)
+ */
+
+#define cco_closure(Name, ...) \
+ struct Name { \
+ int (*cco_fn)(struct Name*); \
+ int cco_state; \
+ __VA_ARGS__ \
+ }
+
+typedef struct cco_base {
+ int (*cco_fn)(struct cco_base*);
+ int cco_state;
+} cco_base;
+
+#define cco_resume(closure) \
+ (closure)->cco_fn(closure)
+
+#define cco_cast(closure) \
+ ((cco_base *)(closure) + 0*sizeof((cco_resume(closure), (int*)0 == &(closure)->cco_state)))
+
+/*
* Semaphore
*/
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, )
-#define cco_sem_await_2(sem, ret) \
+#define cco_sem_await(sem) cco_sem_await_v_2(sem, CCO_AWAIT)
+#define cco_sem_await_v(...) c_MACRO_OVERLOAD(cco_sem_await_v, __VA_ARGS__)
+#define cco_sem_await_v_1(sem) cco_sem_await_v_2(sem, )
+#define cco_sem_await_v_2(sem, ret) \
do { \
- cco_await_2((sem)->count > 0, ret); \
+ cco_await_v_2((sem)->count > 0, ret); \
--(sem)->count; \
} while (0)
@@ -197,12 +218,13 @@ typedef struct { intptr_t count; } cco_sem;
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, sec) cco_timer_await_3(tm, sec, )
-#define cco_timer_await_3(tm, sec, ret) \
+#define cco_timer_await(tm, sec) cco_timer_await_v_3(tm, sec, CCO_AWAIT)
+#define cco_timer_await_v(...) c_MACRO_OVERLOAD(cco_timer_await_v, __VA_ARGS__)
+#define cco_timer_await_v_2(tm, sec) cco_timer_await_v_3(tm, sec, )
+#define cco_timer_await_v_3(tm, sec, ret) \
do { \
cco_timer_start(tm, sec); \
- cco_await_2(cco_timer_expired(tm), ret); \
+ cco_await_v_2(cco_timer_expired(tm), ret); \
} while (0)
static inline void cco_timer_start(cco_timer* tm, double sec) {
diff --git a/include/stc/algo/sort.h b/include/stc/algo/sort.h
index 002e6499..8365ccc5 100644
--- a/include/stc/algo/sort.h
+++ b/include/stc/algo/sort.h
@@ -44,7 +44,7 @@ int main() {
// ex2:
#define i_val int
#define i_type IDeq
-#define i_retain // retain input template params to be reused by sort.h
+#define i_more // retain input template params to be reused by sort.h
#include <stc/cdeq.h>
#include <stc/algo/sort.h>
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index 2db040f1..bac40f90 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -23,11 +23,11 @@
#define _i_prefix cdeq_
#define _pop _pop_front
#define _pull _pull_front
-#ifdef i_retain
+#ifdef i_more
#include "cqueue.h"
- #define i_retain
+ #define i_more
#else
- #define i_retain
+ #define i_more
#include "cqueue.h"
#endif
#undef _pop
diff --git a/include/stc/priv/template2.h b/include/stc/priv/template2.h
index bd8bc5fc..def5d01e 100644
--- a/include/stc/priv/template2.h
+++ b/include/stc/priv/template2.h
@@ -20,8 +20,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#ifdef i_retain
-#undef i_retain
+#ifdef i_more
+#undef i_more
#else
#undef i_type
#undef i_tag