summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authortylov <[email protected]>2023-07-20 14:42:00 +0200
committertylov <[email protected]>2023-07-20 15:00:02 +0200
commit224a04f7fa7549ed94d2a1415eb25829e39a7cca (patch)
tree1d1be262be71b512d334ded99741a64f2aa6ca67
parent313c1d7bb9b92e75801429c1f7f132589860292e (diff)
downloadSTC-modified-224a04f7fa7549ed94d2a1415eb25829e39a7cca.tar.gz
STC-modified-224a04f7fa7549ed94d2a1415eb25829e39a7cca.zip
Added Task-object to coroutines and true stackless execution.
-rw-r--r--docs/ccommon_api.md5
-rw-r--r--docs/cspan_api.md14
-rw-r--r--include/stc/algo/coroutine.h50
-rw-r--r--include/stc/cspan.h12
-rw-r--r--include/stc/cstr.h34
5 files changed, 68 insertions, 47 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index e053f743..1e1ae1aa 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -390,7 +390,10 @@ cco_routine scope; Use `if-else-if` constructs instead.
| | `cco_await_v(condition, ret);` | Suspend until condition is true (return ret)|
| | `cco_await_on(cocall);` | Await on sub-coroutine to finish (return its ret) |
| | `cco_return;` | Return from coroutine (inside cco_routine) |
-| | `cco_closure(Closure, ...);` | Define a coroutine closure struct (optional) |
+| | Task objects: | |
+| | `cco_task_struct(Name, ...);` | Define a coroutine task struct |
+| | `cco_await_task(task, ...);` | Await for task to finish or optionally yield a value |
+| | `cco_block_task(task);` | Run blocking until task is finished (stackless) |
| | Semaphores: | |
| | `cco_sem` | Semaphore type |
| `cco_sem` | `cco_sem_from(long value)` | Create semaphore |
diff --git a/docs/cspan_api.md b/docs/cspan_api.md
index 09821450..e1c92bbf 100644
--- a/docs/cspan_api.md
+++ b/docs/cspan_api.md
@@ -26,14 +26,14 @@ i.e., it may be expanded multiple times. However, all index arguments are safe,
`cspan_at(&ms3, i++, j++, k++)` is allowed. If the number of arguments does not match the span rank,
a compile error is issued. Runtime bounds checks are enabled by default (define `STC_NDEBUG` or `NDEBUG` to disable).
```c
-SpanType cspan_init(T SpanType, {v1, v2, ...}); // make a 1-d cspan from values
-SpanType cspan_from(STCContainer* cnt); // make a 1-d cspan from compatible STC container
-SpanType cspan_from_array(ValueType array[]); // make a 1-d cspan from C array
-
+SpanType cspan_init(TYPE SpanType, {v1, v2, ...}); // make a 1-d cspan from values
+SpanType cspan_from(STCContainer* cnt); // make a 1-d cspan from a cvec, cstack, cpque (heap)
+SpanType cspan_from_array(ValueType array[]); // make a 1-d cspan from a C array
+
intptr_t cspan_size(const SpanTypeN* self); // return number of elements
intptr_t cspan_rank(const SpanTypeN* self); // dimensions; compile time constant
intptr_t cspan_index(const SpanTypeN* self, intptr_t x, ..); // index of element
-
+
ValueType* cspan_at(const SpanTypeN* self, intptr_t x, ...); // #args must match input span rank
ValueType* cspan_front(const SpanTypeN* self);
ValueType* cspan_back(const SpanTypeN* self);
@@ -55,13 +55,13 @@ SpanType2 cspan_subspan2(const SpanType2* span, intptr_t offset, intptr_t
SpanType3 cspan_subspan3(const SpanType3* span, intptr_t offset, intptr_t count);
// create a sub md span of lower rank. Like e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL});
-OutSpan1 cspan_submd2(const SpanType2* parent, intptr_t x); // return a 1d subspan from a 2d span.
+OutSpan cspan_submd2(const SpanType2* parent, intptr_t x); // return a 1d subspan from a 2d span.
OutSpanN cspan_submd3(const SpanType3* parent, intptr_t x, ...); // return a 1d or 2d subspan from a 3d span.
OutSpanN cspan_submd4(const SpanType4* parent, intptr_t x, ...); // number of args decides rank of output span.
// general slicing of an md span.
// {i}: reduce rank. {i,c_END}: slice to end. {c_ALL}: use full extent.
-OutSpanN cspan_slice(TYPE OutSpanN, const SpanTypeN* parent, {x0,x1}, {y0,y1}.., {N0,N1});
+OutSpanN cspan_slice(TYPE OutSpanN, const SpanTypeM* parent, {x0,x1}, {y0,y1}.., {N0,N1});
```
## TypesPd
| Type name | Type definition / usage | Used to represent... |
diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h
index e4c0915c..7c6989c3 100644
--- a/include/stc/algo/coroutine.h
+++ b/include/stc/algo/coroutine.h
@@ -64,9 +64,8 @@ enum {
};
typedef enum {
CCO_DONE = 0,
- CCO_YIELD = 1,
- CCO_AWAIT = 2,
- CCO_ERROR = -1,
+ CCO_AWAIT = 1<<0,
+ CCO_YIELD = 1<<1,
} cco_result;
#define cco_initial(co) ((co)->cco_state == 0)
@@ -132,26 +131,45 @@ typedef enum {
(void)((co)->cco_state = 0)
/*
- * Closure (optional)
+ * Tasks (optional)
*/
-#define cco_closure(Name, ...) \
+struct cco_runtime;
+
+#define cco_task_struct(Name, ...) \
struct Name { \
- int (*cco_fn)(struct Name*); \
- int cco_state; \
+ int (*cco_fn)(struct Name*, struct cco_runtime*); \
+ int cco_state, cco_expect; \
__VA_ARGS__ \
}
-typedef struct cco_base {
- int (*cco_fn)(struct cco_base*);
- int cco_state;
-} cco_base;
+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(closure) \
- (closure)->cco_fn(closure)
+#define cco_resume(task, rt) \
+ (task)->cco_fn(task, rt)
-#define cco_cast(closure) \
- ((cco_base *)(closure) + 0*sizeof((cco_resume(closure), (int*)0 == &(closure)->cco_state)))
+#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
@@ -182,7 +200,7 @@ typedef struct { intptr_t count; } cco_sem;
#else
#define _c_LINKC __declspec(dllimport)
#endif
- #if _WIN32_WINNT < _WIN32_WINNT_WIN8 || defined __TINYC__
+ #if 1 // _WIN32_WINNT < _WIN32_WINNT_WIN8 || defined __TINYC__
#define _c_getsystime GetSystemTimeAsFileTime
#else
#define _c_getsystime GetSystemTimePreciseAsFileTime
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index dcb02961..08045010 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -80,19 +80,19 @@ int demo2() {
STC_INLINE Self Self##_from_n(Self##_raw* raw, const intptr_t n) { \
return (Self){.data=raw, .shape={(int32_t)n}}; \
} \
- STC_INLINE Self Self##_slice_(Self##_value* v, const int32_t shape[], const int32_t stri[], \
+ STC_INLINE Self Self##_slice_(Self##_value* d, const int32_t shape[], const int32_t stri[], \
const int rank, const int32_t a[][2]) { \
- Self s; s.data = v; int outrank; \
- s.data += _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \
+ Self s; int outrank; \
+ s.data = d + _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \
c_assert(outrank == RANK); \
return s; \
} \
STC_INLINE Self##_iter Self##_begin(const Self* self) { \
- Self##_iter it = {.ref=self->data, .pos={0}, ._s=self}; \
+ Self##_iter it = {.ref=self->data, ._s=self}; \
return it; \
} \
STC_INLINE Self##_iter Self##_end(const Self* self) { \
- Self##_iter it = {.ref=NULL}; \
+ Self##_iter it = {0}; \
return it; \
} \
STC_INLINE void Self##_next(Self##_iter* it) { \
@@ -120,7 +120,7 @@ using_cspan_tuple(7); using_cspan_tuple(8);
#define cspan_init(SpanType, ...) \
{.data=(SpanType##_value[])__VA_ARGS__, .shape={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}, .stride={.d={1}}}
-/* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */
+/* create a cspan from a cvec, cstack, or cpque (heap) */
#define cspan_from(container) \
{.data=(container)->data, .shape={(int32_t)(container)->_len}, .stride={.d={1}}}
diff --git a/include/stc/cstr.h b/include/stc/cstr.h
index 17943ad5..2648e267 100644
--- a/include/stc/cstr.h
+++ b/include/stc/cstr.h
@@ -170,14 +170,14 @@ STC_INLINE intptr_t cstr_capacity(const cstr* self)
// utf8 methods defined in/depending on src/utf8code.c:
-STC_API cstr cstr_casefold_sv(csview sv);
-STC_API cstr cstr_tolower_sv(csview sv);
-STC_API cstr cstr_toupper_sv(csview sv);
-STC_API cstr cstr_tolower(const char* str);
-STC_API cstr cstr_toupper(const char* str);
-STC_API void cstr_lowercase(cstr* self);
-STC_API void cstr_uppercase(cstr* self);
-STC_API bool cstr_valid_utf8(const cstr* self);
+extern cstr cstr_casefold_sv(csview sv);
+extern cstr cstr_tolower_sv(csview sv);
+extern cstr cstr_toupper_sv(csview sv);
+extern cstr cstr_tolower(const char* str);
+extern cstr cstr_toupper(const char* str);
+extern void cstr_lowercase(cstr* self);
+extern void cstr_uppercase(cstr* self);
+extern bool cstr_valid_utf8(const cstr* self);
// other utf8
@@ -394,7 +394,7 @@ fn_tocase[] = {{tolower, utf8_casefold},
{tolower, utf8_tolower},
{toupper, utf8_toupper}};
-STC_DEF cstr cstr_tocase(csview sv, int k) {
+static cstr cstr_tocase(csview sv, int k) {
cstr out = cstr_init();
char *buf = cstr_reserve(&out, sv.size*3/2);
const char *end = sv.str + sv.size;
@@ -415,28 +415,28 @@ STC_DEF cstr cstr_tocase(csview sv, int k) {
return out;
}
-STC_DEF cstr cstr_casefold_sv(csview sv)
+cstr cstr_casefold_sv(csview sv)
{ return cstr_tocase(sv, 0); }
-STC_DEF cstr cstr_tolower_sv(csview sv)
+cstr cstr_tolower_sv(csview sv)
{ return cstr_tocase(sv, 1); }
-STC_DEF cstr cstr_toupper_sv(csview sv)
+cstr cstr_toupper_sv(csview sv)
{ return cstr_tocase(sv, 2); }
-STC_DEF cstr cstr_tolower(const char* str)
+cstr cstr_tolower(const char* str)
{ return cstr_tolower_sv(c_sv(str, c_strlen(str))); }
-STC_DEF cstr cstr_toupper(const char* str)
+cstr cstr_toupper(const char* str)
{ return cstr_toupper_sv(c_sv(str, c_strlen(str))); }
-STC_DEF void cstr_lowercase(cstr* self)
+void cstr_lowercase(cstr* self)
{ cstr_take(self, cstr_tolower_sv(cstr_sv(self))); }
-STC_DEF void cstr_uppercase(cstr* self)
+void cstr_uppercase(cstr* self)
{ cstr_take(self, cstr_toupper_sv(cstr_sv(self))); }
-STC_DEF bool cstr_valid_utf8(const cstr* self)
+bool cstr_valid_utf8(const cstr* self)
{ return utf8_valid(cstr_str(self)); }
#endif // i_import