summaryrefslogtreecommitdiffhomepage
path: root/include/stc/algo/coroutine.h
diff options
context:
space:
mode:
authortylov <[email protected]>2023-07-21 00:37:28 +0200
committertylov <[email protected]>2023-07-21 00:37:28 +0200
commit2d67f4040f6eecd41f1b864b43c62823ed75aff0 (patch)
tree084ce603dc4edfa1ccad3aabab5b671a817bc67e /include/stc/algo/coroutine.h
parent900295256d825fc323149cd223c49787f32a3696 (diff)
downloadSTC-modified-2d67f4040f6eecd41f1b864b43c62823ed75aff0.tar.gz
STC-modified-2d67f4040f6eecd41f1b864b43c62823ed75aff0.zip
Renamed badly abbreviated names in crand.h.
Moved coroutine.h from algo subfolder to stc. Updated coroutine.h and docs.
Diffstat (limited to 'include/stc/algo/coroutine.h')
-rw-r--r--include/stc/algo/coroutine.h274
1 files changed, 0 insertions, 274 deletions
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
deleted file mode 100644
index 7c6989c3..00000000
--- a/include/stc/algo/coroutine.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2023 Tyge Løvset
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef STC_COROUTINE_INCLUDED
-#define STC_COROUTINE_INCLUDED
-/*
-#include <stdio.h>
-#include <stc/algo/coroutine.h>
-
-struct iterpair {
- int max_x, max_y;
- int x, y;
- int cco_state; // required member
-};
-
-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();
-
- cco_cleanup: // required if there is cleanup code
- puts("final");
- }
- return 0; // CCO_DONE
-}
-
-int main(void) {
- struct iterpair it = {.max_x=3, .max_y=3};
- int n = 0;
- while (iterpair(&it))
- {
- printf("%d %d\n", it.x, it.y);
- // example of early stop:
- if (++n == 7) cco_stop(&it); // signal to stop/finalize in next
- }
- return 0;
-}
-*/
-#include "../ccommon.h"
-
-enum {
- CCO_STATE_CLEANUP = -1,
- CCO_STATE_DONE = -2,
-};
-typedef enum {
- CCO_DONE = 0,
- CCO_AWAIT = 1<<0,
- CCO_YIELD = 1<<1,
-} cco_result;
-
-#define cco_initial(co) ((co)->cco_state == 0)
-#define cco_suspended(co) ((co)->cco_state > 0)
-#define cco_done(co) ((co)->cco_state == CCO_STATE_DONE)
-
-#define cco_routine(co) \
- for (int *_state = &(co)->cco_state; *_state != CCO_STATE_DONE; *_state = CCO_STATE_DONE) \
- _resume: switch (*_state) case 0: // thanks, @liigo!
-
-#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(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)
-
-/* 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(corocall) while ((corocall) != CCO_DONE)
-#define cco_block_on_2(corocall, result) while ((*(result) = (corocall)) != CCO_DONE)
-
-#define cco_cleanup \
- *_state = CCO_STATE_CLEANUP; case CCO_STATE_CLEANUP
-
-#define cco_return \
- do { \
- *_state = *_state >= 0 ? CCO_STATE_CLEANUP : CCO_STATE_DONE; \
- goto _resume; \
- } while (0)
-
-#define cco_yield_final() cco_yield_final_v(CCO_YIELD)
-#define cco_yield_final_v(value) \
- do { \
- *_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_CLEANUP; \
- else if (*_s == 0) *_s = CCO_STATE_DONE; \
- } while (0)
-
-#define cco_reset(co) \
- (void)((co)->cco_state = 0)
-
-/*
- * Tasks (optional)
- */
-
-struct cco_runtime;
-
-#define cco_task_struct(Name, ...) \
- struct Name { \
- int (*cco_fn)(struct Name*, struct cco_runtime*); \
- int cco_state, cco_expect; \
- __VA_ARGS__ \
- }
-
-typedef cco_task_struct(cco_task, /**/) cco_task;
-
-typedef struct cco_runtime {
- int result, top;
- cco_task* stack[];
-} cco_runtime;
-
-#define cco_cast_task(task) \
- ((cco_task *)(task) + 0*sizeof((task)->cco_fn(task, (cco_runtime*)0) + ((int*)0 == &(task)->cco_state)))
-
-#define cco_resume(task, rt) \
- (task)->cco_fn(task, rt)
-
-#define cco_block_task(...) c_MACRO_OVERLOAD(cco_block_task, __VA_ARGS__)
-#define cco_block_task_1(task) cco_block_task_3(task, rt, 16)
-#define cco_block_task_3(task, rt, STACKDEPTH) \
- for (struct { int result, top; cco_task* stack[STACKDEPTH]; } rt = {.stack={cco_cast_task(task)}}; \
- (((rt.result = cco_resume(rt.stack[rt.top], (cco_runtime*)&rt)) & rt.stack[rt.top]->cco_expect) || --rt.top >= 0); )
-
-#define cco_await_task(...) c_MACRO_OVERLOAD(cco_await_task, __VA_ARGS__)
-#define cco_await_task_2(task, rt) cco_await_task_3(task, rt, CCO_DONE)
-#define cco_await_task_3(task, rt, resultbits) \
- do { \
- cco_runtime* _rt = rt; \
- (_rt->stack[++_rt->top] = cco_cast_task(task))->cco_expect = ~(resultbits); \
- cco_yield_v(CCO_AWAIT); \
- } while (0)
-
-/*
- * Semaphore
- */
-
-typedef struct { intptr_t count; } cco_sem;
-
-#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_v_2((sem)->count > 0, ret); \
- --(sem)->count; \
- } while (0)
-
-#define cco_sem_release(sem) ++(sem)->count
-#define cco_sem_from(value) ((cco_sem){value})
-#define cco_sem_set(sem, value) ((sem)->count = value)
-
-/*
- * Timer
- */
-
-#ifdef _WIN32
- #ifdef __cplusplus
- #define _c_LINKC extern "C" __declspec(dllimport)
- #else
- #define _c_LINKC __declspec(dllimport)
- #endif
- #if 1 // _WIN32_WINNT < _WIN32_WINNT_WIN8 || defined __TINYC__
- #define _c_getsystime GetSystemTimeAsFileTime
- #else
- #define _c_getsystime GetSystemTimePreciseAsFileTime
- #endif
- struct _FILETIME;
- _c_LINKC void _c_getsystime(struct _FILETIME*);
- _c_LINKC void Sleep(unsigned long);
-
- static inline double cco_time(void) { /* seconds since epoch */
- unsigned long long quad; /* 64-bit value representing 1/10th usecs since Jan 1 1601, 00:00 UTC */
- _c_getsystime((struct _FILETIME*)&quad);
- 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) {
- Sleep((unsigned long)(sec*1000.0));
- }
-#else
- #include <sys/time.h>
- static inline double cco_time(void) { /* seconds since epoch */
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (double)tv.tv_sec + (double)tv.tv_usec*1e-6;
- }
-
- static inline void cco_sleep(double sec) {
- struct timeval tv;
- tv.tv_sec = (time_t)sec;
- tv.tv_usec = (suseconds_t)((sec - (double)(long)sec)*1e6);
- select(0, NULL, NULL, NULL, &tv);
- }
-#endif
-
-typedef struct { double interval, start; } cco_timer;
-
-#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_v_2(cco_timer_expired(tm), ret); \
- } while (0)
-
-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(double sec) {
- cco_timer tm = {.interval=sec, .start=cco_time()};
- return tm;
-}
-
-static inline void cco_timer_restart(cco_timer* tm) {
- tm->start = cco_time();
-}
-
-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();
-}
-
-#endif