Skip to content

Commit

Permalink
bug fix vector faults, stage coroutine support
Browse files Browse the repository at this point in the history
- added core coroutine implementation from https://github.com/zelang-dev/c-coroutine only `ucontext.h`, not low level assembler. The implementation of `thrd_spawn` and example `thrd_spawn_fib_pool.c` not even possible without it. Should behave similar to https://www.opencilk.org/doc/tutorials/introduction-to-cilk-programming/ which it mimics. Feature will only be  available if `USE_CORO` is defined.
- added an `main` macro to point `main` to launch `coro_main`, or `raii_main` if `USE_CORO` defined.
- Fix test and examples to handle `main` macro
  • Loading branch information
TheTechsTech committed Dec 29, 2024
1 parent e66360f commit 61c87e7
Show file tree
Hide file tree
Showing 23 changed files with 1,589 additions and 524 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,17 +373,22 @@ C_API void args_returning_set(args_t);
*/
C_API arrays_t array_of(memory_t *, size_t, ...);
C_API void array_deferred_set(arrays_t, memory_t *);
C_API void array_append(arrays_t, void_t);
C_API void array_delete(arrays_t);
C_API void array_remove(arrays_t, int);
C_API bool is_array(void_t);
#define $append(arr, value) array_append((arrays_t)arr, (void_t)value)
#define $remove(arr, index) array_remove((arrays_t)arr, index)

#define vectorize(vec) vectors_t vec = vector_variant()
#define vector(vec, count, ...) vectors_t vec = vector_for(nil, count, __VA_ARGS__)

#define $push_back(vec, value) vector_push_back(vec, (void_t)value)
#define $insert(vec, index, value) vector_insert(vec, index, (void_t)value)
#define $clear(vec) vector_clear(vec)
#define $size(vec) vector_size(vec)
#define $capacity(vec) vector_capacity(vec)
#define $erase(vec, index) vector_erase(vec, index)
#define $push_back(vec, value) vector_push_back((vectors_t)vec, (void_t)value)
#define $insert(vec, index, value) vector_insert((vectors_t)vec, index, (void_t)value)
#define $clear(vec) vector_clear((vectors_t)vec)
#define $size(vec) vector_size((vectors_t)vec)
#define $capacity(vec) vector_capacity((vectors_t)vec)
#define $erase(vec, index) vector_erase((vectors_t)vec, index)

/* The `foreach(item in vector/array)` macro, similar to `C#`,
executes a statement or a block of statements for each element in
Expand Down
17 changes: 11 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,22 @@ C_API void args_returning_set(args_t);
*/
C_API arrays_t array_of(memory_t *, size_t, ...);
C_API void array_deferred_set(arrays_t, memory_t *);
C_API void array_append(arrays_t, void_t);
C_API void array_delete(arrays_t);
C_API void array_remove(arrays_t, int);
C_API bool is_array(void_t);
#define $append(arr, value) array_append((arrays_t)arr, (void_t)value)
#define $remove(arr, index) array_remove((arrays_t)arr, index)

#define vectorize(vec) vectors_t vec = vector_variant()
#define vector(vec, count, ...) vectors_t vec = vector_for(nil, count, __VA_ARGS__)

#define $push_back(vec, value) vector_push_back(vec, (void_t)value)
#define $insert(vec, index, value) vector_insert(vec, index, (void_t)value)
#define $clear(vec) vector_clear(vec)
#define $size(vec) vector_size(vec)
#define $capacity(vec) vector_capacity(vec)
#define $erase(vec, index) vector_erase(vec, index)
#define $push_back(vec, value) vector_push_back((vectors_t)vec, (void_t)value)
#define $insert(vec, index, value) vector_insert((vectors_t)vec, index, (void_t)value)
#define $clear(vec) vector_clear((vectors_t)vec)
#define $size(vec) vector_size((vectors_t)vec)
#define $capacity(vec) vector_capacity((vectors_t)vec)
#define $erase(vec, index) vector_erase((vectors_t)vec, index)

/* The `foreach(item in vector/array)` macro, similar to `C#`,
executes a statement or a block of statements for each element in
Expand Down
2 changes: 1 addition & 1 deletion examples/defer_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static unsigned int names[max_threads];
static thrd_t threads[max_threads];

void defer_capture(void *arg) {
thrd_t thrd = raii_value(arg).thread;
thrd_t thrd = *(thrd_t *)raii_value(arg).object;
if (thrd_success != thrd_join(thrd, NULL)) {
puts("main: thrd_join failure");
thrd_exit(EXIT_FAILURE);
Expand Down
1 change: 1 addition & 0 deletions examples/thrd_async.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "raii.h"

/* Plain C89 version of https://cplusplus.com/reference/future/future/wait/
// future::wait
Expand Down
2 changes: 2 additions & 0 deletions examples/thrd_spawn_fib_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
void_t fib(args_t args) {
int n = get_arg(args).integer;
if (n < 2) {
RAII_HERE;
return thrd_value(n);
} else {
result_t x, y;
Expand Down Expand Up @@ -32,6 +33,7 @@ int main(int argc, char **argv) {
result_t results = thrd_spawn(fib, thrd_value(n));

thrd_sync(fut);
RAII_HERE;
printf("Result: %d\n", thrd_result(results).integer);

return 0;
Expand Down
2 changes: 1 addition & 1 deletion examples/try_catch.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ static int idiv(int a, int b) {
return a / b;
}

int main(void) {
int main(int argc, char **argv){
try {
idiv(1, 0);
printf("never reached\n");
Expand Down
2 changes: 1 addition & 1 deletion examples/try_catch_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ static int idiv(int a, int b) {
return a / b;
}

int main(void) {
int main(int argc, char **argv){
try {
idiv(1, 0);
printf("never reached\n");
Expand Down
2 changes: 1 addition & 1 deletion examples/try_free_protected.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ static void pfree(void *p) {
free(p);
}

int main(void) {
int main(int argc, char **argv){
try {
char *p1 = 0; protected(p1, pfree);
char *p2 = 0; protected(p2, pfree);
Expand Down
2 changes: 1 addition & 1 deletion examples/try_protect.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ static void pfree(void *p) {
free(p);
}

int main(void) {
int main(int argc, char **argv){
try {
char *p = 0; protected(p, pfree);

Expand Down
2 changes: 1 addition & 1 deletion examples/try_rethrow.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ static int idiv(int a, int b) {
return a / b;
}

int main(void) {
int main(int argc, char **argv){
try {
idiv(1, 0);
printf("never reached\n");
Expand Down
117 changes: 117 additions & 0 deletions include/coro.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@

#ifndef _CORO_H
#define _CORO_H

#define _BSD_SOURCE

/* Public API qualifier. */
#ifndef C_API
# define C_API extern
#endif

/* Coroutine states. */
typedef enum {
CORO_EVENT_DEAD = -1, /* The coroutine has ended it's Event Loop routine, is uninitialized or deleted. */
CORO_DEAD, /* The coroutine is uninitialized or deleted. */
CORO_NORMAL, /* The coroutine is active but not running (that is, it has switch to another coroutine, suspended). */
CORO_RUNNING, /* The coroutine is active and running. */
CORO_SUSPENDED, /* The coroutine is suspended (in a startup, or it has not started running yet). */
CORO_EVENT, /* The coroutine is in an Event Loop callback. */
CORO_ERRED, /* The coroutine has erred. */
} coro_states;

typedef enum {
CORO_RUN_NORMAL,
CORO_RUN_MAIN,
CORO_RUN_THRD,
CORO_RUN_SYSTEM,
CORO_RUN_EVENT,
CORO_RUN_ASYNC,
} run_mode;

typedef struct routine_s routine_t;
typedef struct raii_deque_s raii_deque_t;
#if __APPLE__ && __MACH__
# include <sys/ucontext.h>
#elif defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
# include <windows.h>
# if defined(_X86_)
# define DUMMYARGS
# else
# define DUMMYARGS long dummy0, long dummy1, long dummy2, long dummy3,
# endif
typedef struct __stack {
void *ss_sp;
size_t ss_size;
int ss_flags;
} stack_t;

typedef CONTEXT mcontext_t;
typedef unsigned long __sigset_t;

typedef struct __ucontext {
unsigned long int uc_flags;
struct __ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
__sigset_t uc_sigmask;
} ucontext_t;

C_API int getcontext(ucontext_t *ucp);
C_API int setcontext(const ucontext_t *ucp);
C_API int makecontext(ucontext_t *, void (*)(), int, ...);
C_API int swapcontext(routine_t *, const routine_t *);
#else
# include <ucontext.h>
#endif

#ifdef USE_CORO
#define main(...) \
main(int argc, char** argv) { \
return raii_main(argc, argv); \
} \
int coro_main(__VA_ARGS__)
#else
#define main(...) \
main(int argc, char** argv) { \
return coro_main(argc, argv); \
} \
int coro_main(__VA_ARGS__)
#endif

#ifndef CORO_STACK_SIZE
/* Stack size when creating a coroutine. */
# define CORO_STACK_SIZE (8 * 1024)
#endif

#ifndef ERROR_SCRAPE_SIZE
# define ERROR_SCRAPE_SIZE 256
#endif

#ifndef SCRAPE_SIZE
# define SCRAPE_SIZE (2 * 64)
#endif

/* Number used only to assist checking for stack overflows. */
#define CORO_MAGIC_NUMBER 0x7E3CB1A9

#ifdef __cplusplus
extern "C" {
#endif
C_API void coro_yield(void);
C_API routine_t *coro_active(void);
C_API unsigned int coro_sleep_for(unsigned int ms);
C_API void coro_deferred_free(routine_t *);

/* This library provides its own ~main~,
which call this function as an coroutine! */
C_API int coro_main(int, char **);
C_API int raii_main(int, char **);


#ifdef __cplusplus
}
#endif


#endif /* _CORO_H */
Loading

0 comments on commit 61c87e7

Please sign in to comment.