Implemented async better.

This commit is contained in:
2025-11-23 20:30:37 +01:00
parent e5f6f89764
commit 327eeadca4
10 changed files with 813 additions and 16 deletions
+2
View File
@@ -17,3 +17,5 @@ char str_pool[STR_POOL_SIZE];
int str_pool_idx = 0;
long ax = 0;
int return_flag = 0;
Coroutine coroutines[MAX_COROUTINES];
int coroutine_count = 0;
+13 -5
View File
@@ -241,18 +241,26 @@ void statement() {
void scan_functions() {
int i = 0;
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
(tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) &&
tokens[i+1].type == Id && tokens[i+2].type == '(') {
int is_async = 0;
int offset = 0;
if (tokens[i].type == Async) {
is_async = 1;
offset = 1;
}
if (i + 2 + offset < MAX_TOK && i + 2 + offset < tk_idx &&
(tokens[i+offset].type == Int || tokens[i+offset].type == Char || tokens[i+offset].type == Double) &&
tokens[i+1+offset].type == Id && tokens[i+2+offset].type == '(') {
if (func_cnt >= 100) {
error("Too many functions defined");
}
Func *f = &funcs[func_cnt++];
Token *name = &tokens[i+1];
Token *name = &tokens[i+1+offset];
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
f->is_async = is_async;
i += 3;
i += 3 + offset;
f->params_start = i;
int params = 0;
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
+255
View File
@@ -1035,6 +1035,259 @@ long native_async_result(long *args, int argc) {
return result;
}
static pthread_mutex_t coroutine_mutex = PTHREAD_MUTEX_INITIALIZER;
static int coroutine_initialized = 0;
void init_coroutines() {
if (!coroutine_initialized) {
pthread_mutex_lock(&coroutine_mutex);
for (int i = 0; i < MAX_COROUTINES; i++) {
coroutines[i].active = 0;
coroutines[i].complete = 0;
coroutines[i].result = 0;
coroutines[i].thread = NULL;
}
coroutine_count = 0;
coroutine_initialized = 1;
pthread_mutex_unlock(&coroutine_mutex);
}
}
int alloc_coroutine() {
init_coroutines();
pthread_mutex_lock(&coroutine_mutex);
for (int i = 0; i < MAX_COROUTINES; i++) {
if (!coroutines[i].active) {
coroutines[i].active = 1;
coroutines[i].complete = 0;
coroutines[i].result = 0;
pthread_mutex_unlock(&coroutine_mutex);
return i;
}
}
pthread_mutex_unlock(&coroutine_mutex);
return -1;
}
typedef struct {
int coroutine_id;
} CoroutineThreadData;
void* coroutine_thread_func(void *arg) {
CoroutineThreadData *data = (CoroutineThreadData*)arg;
int coro_id = data->coroutine_id;
free(data);
if (coro_id < 0 || coro_id >= MAX_COROUTINES) {
return NULL;
}
Coroutine *coro = &coroutines[coro_id];
int func_idx = coro->func_idx;
int argc = coro->argc;
long args[10];
for (int i = 0; i < argc && i < 10; i++) {
args[i] = coro->args[i];
}
if (func_idx < 0 || func_idx >= func_cnt) {
pthread_mutex_lock(&coroutine_mutex);
coro->complete = 1;
coro->result = 0;
pthread_mutex_unlock(&coroutine_mutex);
return NULL;
}
pthread_mutex_lock(&coroutine_mutex);
long saved_memory[MEM_SIZE];
Symbol saved_locals[VAR_MAX];
int saved_pc, saved_sp, saved_bp, saved_loc_cnt;
long saved_ax;
int saved_return_flag;
for (int i = 0; i < MEM_SIZE; i++) {
saved_memory[i] = memory[i];
}
for (int i = 0; i < loc_cnt && i < VAR_MAX; i++) {
saved_locals[i] = locals[i];
}
saved_pc = pc;
saved_sp = sp;
saved_bp = bp;
saved_loc_cnt = loc_cnt;
saved_ax = ax;
saved_return_flag = return_flag;
int old_loc_cnt = loc_cnt;
if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) {
pthread_mutex_unlock(&coroutine_mutex);
coro->complete = 1;
coro->result = 0;
return NULL;
}
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE) {
pthread_mutex_unlock(&coroutine_mutex);
coro->complete = 1;
coro->result = 0;
return NULL;
}
memory[sp++] = 0;
memory[sp++] = old_loc_cnt;
int param_base = sp;
for (int i = 0; i < argc && i < 10; i++) {
if (sp >= MEM_SIZE) break;
memory[sp++] = args[i];
}
int scan_pc = funcs[func_idx].params_start;
int param_idx = 0;
while (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
if (tokens[scan_pc].type == Int || tokens[scan_pc].type == Char || tokens[scan_pc].type == Double) {
scan_pc++;
while (scan_pc < MAX_TOK && tokens[scan_pc].type == '*') scan_pc++;
if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc && loc_cnt < VAR_MAX) {
Token *param_name = &tokens[scan_pc];
Symbol *sym = &locals[loc_cnt++];
int name_len = param_name->val;
if (name_len > 31) name_len = 31;
strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0;
sym->type = Int;
sym->addr = param_base + param_idx;
sym->is_array = 0;
param_idx++;
}
}
scan_pc++;
}
pc = funcs[func_idx].entry_point;
return_flag = 0;
ax = 0;
extern void statement();
statement();
long result_val = ax;
for (int i = 0; i < MEM_SIZE; i++) {
memory[i] = saved_memory[i];
}
for (int i = 0; i < saved_loc_cnt && i < VAR_MAX; i++) {
locals[i] = saved_locals[i];
}
pc = saved_pc;
sp = saved_sp;
bp = saved_bp;
loc_cnt = saved_loc_cnt;
ax = saved_ax;
return_flag = saved_return_flag;
coro->result = result_val;
coro->complete = 1;
pthread_mutex_unlock(&coroutine_mutex);
return NULL;
}
int create_coroutine(int func_idx, long *args, int argc) {
int coro_id = alloc_coroutine();
if (coro_id < 0) {
return -1;
}
Coroutine *coro = &coroutines[coro_id];
pthread_mutex_lock(&coroutine_mutex);
coro->func_idx = func_idx;
coro->argc = argc;
for (int i = 0; i < argc && i < 10; i++) {
coro->args[i] = args[i];
}
pthread_mutex_unlock(&coroutine_mutex);
CoroutineThreadData *thread_data = malloc(sizeof(CoroutineThreadData));
thread_data->coroutine_id = coro_id;
pthread_t *thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, coroutine_thread_func, thread_data);
pthread_mutex_lock(&coroutine_mutex);
coro->thread = thread;
pthread_mutex_unlock(&coroutine_mutex);
return coro_id;
}
long native_await(long *args, int argc) {
if (!args || argc < 1) return 0;
int coro_id = (int)args[0];
if (coro_id < 0 || coro_id >= MAX_COROUTINES) {
return 0;
}
Coroutine *coro = &coroutines[coro_id];
if (!coro->active) {
return 0;
}
pthread_t *thread = (pthread_t*)coro->thread;
if (thread) {
pthread_join(*thread, NULL);
free(thread);
coro->thread = NULL;
}
pthread_mutex_lock(&coroutine_mutex);
long result = coro->result;
coro->active = 0;
pthread_mutex_unlock(&coroutine_mutex);
return result;
}
long native_gather(long *args, int argc) {
if (!args || argc < 1) return 0;
int coro_ids[100];
int count = 0;
for (int i = 0; i < argc && i < 100; i++) {
coro_ids[count++] = (int)args[i];
}
for (int i = 0; i < count; i++) {
int coro_id = coro_ids[i];
if (coro_id < 0 || coro_id >= MAX_COROUTINES) continue;
Coroutine *coro = &coroutines[coro_id];
if (!coro->active) continue;
pthread_t *thread = (pthread_t*)coro->thread;
if (thread) {
pthread_join(*thread, NULL);
free(thread);
coro->thread = NULL;
}
pthread_mutex_lock(&coroutine_mutex);
coro->active = 0;
pthread_mutex_unlock(&coroutine_mutex);
}
return 1;
}
void register_native_functions() {
register_native_func("socket", native_socket);
register_native_func("bind", native_bind);
@@ -1089,4 +1342,6 @@ void register_native_functions() {
register_native_func("async_wait", native_async_wait);
register_native_func("async_poll", native_async_poll);
register_native_func("async_result", native_async_result);
register_native_func("await", native_await);
register_native_func("gather", native_gather);
}
+1
View File
@@ -3,5 +3,6 @@
void register_native_func(char *name, NativeFunc func);
void register_native_functions();
int create_coroutine(int func_idx, long *args, int argc);
#endif
+17 -1
View File
@@ -31,7 +31,18 @@ long factor() {
Token *t = &tokens[pc];
long val = 0;
if (t->type == Num) {
if (t->type == Await) {
pc++;
match('(');
long coro_id = expression();
match(')');
extern long native_await(long*, int);
long args[1];
args[0] = coro_id;
return native_await(args, 1);
}
else if (t->type == Num) {
pc++;
return t->val;
}
@@ -94,6 +105,11 @@ long factor() {
}
match(')');
if (funcs[f_idx].is_async) {
extern int create_coroutine(int func_idx, long *args, int argc);
return create_coroutine(f_idx, args, argc);
}
int ret_pc = pc;
int old_loc_cnt = loc_cnt;
int old_bp = bp;
+2
View File
@@ -42,6 +42,8 @@ void tokenize(char *src) {
else if (!strcmp(buf, "printf")) t->type = Printf;
else if (!strcmp(buf, "break")) t->type = Break;
else if (!strcmp(buf, "continue")) t->type = Continue;
else if (!strcmp(buf, "async")) t->type = Async;
else if (!strcmp(buf, "await")) t->type = Await;
else t->type = Id;
t->val = len;
+22 -1
View File
@@ -9,7 +9,7 @@
enum {
Num = 128, Dbl, Str, Id, Int, Char, Double, Else, If, While, Return, Printf,
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue, Async, Await
};
typedef struct {
@@ -31,6 +31,7 @@ typedef struct {
int entry_point;
int param_count;
int params_start;
int is_async;
} Func;
typedef long (*NativeFunc)(long*, int);
@@ -40,6 +41,24 @@ typedef struct {
NativeFunc func;
} NativeFuncDef;
#define MAX_COROUTINES 100
typedef struct Coroutine {
int active;
int complete;
long result;
void *thread;
int func_idx;
long args[10];
int argc;
int pc_saved;
int sp_saved;
int bp_saved;
int loc_cnt_saved;
Symbol locals_saved[VAR_MAX];
long memory_saved[MEM_SIZE];
} Coroutine;
extern Token tokens[MAX_TOK];
extern int tk_idx;
extern int pc;
@@ -57,5 +76,7 @@ extern char str_pool[STR_POOL_SIZE];
extern int str_pool_idx;
extern long ax;
extern int return_flag;
extern Coroutine coroutines[MAX_COROUTINES];
extern int coroutine_count;
#endif