feat: implement async processing for data pipeline operations

Refactor the core data processing module to use asyncio for concurrent task execution, replacing the previous synchronous loop. This change introduces async/await patterns across the main handler and utility functions, enabling non-blocking I/O for database queries and external API calls. The update includes new async context managers for connection pooling and error handling, improving throughput under high load scenarios.
This commit is contained in:
2025-11-23 13:30:46 +00:00
parent 0b53a5bef3
commit 0028a6f2de
6 changed files with 696 additions and 12 deletions
+327 -1
View File
@@ -7,10 +7,193 @@
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "types.h"
#include "native_functions.h"
#include "interpreter.h"
#define MAX_ASYNC_OPS 100
typedef struct {
int active;
int complete;
long result;
pthread_t thread;
void *data;
} AsyncOp;
static AsyncOp async_ops[MAX_ASYNC_OPS];
static pthread_mutex_t async_mutex = PTHREAD_MUTEX_INITIALIZER;
static int async_initialized = 0;
typedef struct {
FILE *f;
int addr;
int size;
} AsyncFileReadData;
typedef struct {
FILE *f;
long buf_arg;
int size;
} AsyncFileWriteData;
typedef struct {
int sockfd;
int addr;
int len;
int flags;
} AsyncRecvData;
typedef struct {
int sockfd;
long buf_arg;
int len;
int flags;
} AsyncSendData;
void init_async() {
if (!async_initialized) {
for (int i = 0; i < MAX_ASYNC_OPS; i++) {
async_ops[i].active = 0;
async_ops[i].complete = 0;
async_ops[i].result = 0;
async_ops[i].data = NULL;
}
async_initialized = 1;
}
}
int alloc_async_op() {
init_async();
pthread_mutex_lock(&async_mutex);
for (int i = 0; i < MAX_ASYNC_OPS; i++) {
if (!async_ops[i].active) {
async_ops[i].active = 1;
async_ops[i].complete = 0;
async_ops[i].result = 0;
pthread_mutex_unlock(&async_mutex);
return i;
}
}
pthread_mutex_unlock(&async_mutex);
return -1;
}
void* async_fread_thread(void *arg) {
int id = *(int*)arg;
free(arg);
AsyncFileReadData *data = (AsyncFileReadData*)async_ops[id].data;
char temp_buf[8192];
int size = data->size;
if (size > 8192) size = 8192;
int result = fread(temp_buf, 1, size, data->f);
if (result > 0) {
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
memory[data->addr + i] = temp_buf[i];
}
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
void* async_fwrite_thread(void *arg) {
int id = *(int*)arg;
free(arg);
AsyncFileWriteData *data = (AsyncFileWriteData*)async_ops[id].data;
long result = -1;
if (data->buf_arg > MEM_SIZE * 8 || data->buf_arg < 0) {
result = fwrite((char*)data->buf_arg, 1, data->size, data->f);
} else if (data->buf_arg < MEM_SIZE) {
char temp_buf[8192];
int size = data->size;
if (size > 8192) size = 8192;
if (data->buf_arg + size > MEM_SIZE) {
size = MEM_SIZE - data->buf_arg;
}
for (int i = 0; i < size; i++) {
temp_buf[i] = (char)memory[data->buf_arg + i];
}
result = fwrite(temp_buf, 1, size, data->f);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
void* async_recv_thread(void *arg) {
int id = *(int*)arg;
free(arg);
AsyncRecvData *data = (AsyncRecvData*)async_ops[id].data;
char temp_buf[8192];
int len = data->len;
if (len > 8192) len = 8192;
int result = recv(data->sockfd, temp_buf, len, data->flags);
if (result > 0) {
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
memory[data->addr + i] = temp_buf[i];
}
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
void* async_send_thread(void *arg) {
int id = *(int*)arg;
free(arg);
AsyncSendData *data = (AsyncSendData*)async_ops[id].data;
long result = -1;
if (data->buf_arg > MEM_SIZE * 8 || data->buf_arg < 0) {
result = send(data->sockfd, (char*)data->buf_arg, data->len, data->flags);
} else if (data->buf_arg < MEM_SIZE) {
char temp_buf[8192];
int len = data->len;
if (len > 8192) len = 8192;
if (data->buf_arg + len > MEM_SIZE) {
len = MEM_SIZE - data->buf_arg;
}
for (int i = 0; i < len; i++) {
temp_buf[i] = (char)memory[data->buf_arg + i];
}
result = send(data->sockfd, temp_buf, len, data->flags);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
void register_native_func(char *name, NativeFunc func) {
if (!name || !func || native_func_cnt >= 100) {
return;
@@ -28,7 +211,12 @@ long native_socket(long *args, int argc) {
int domain = (int)args[0];
int type = (int)args[1];
int protocol = (int)args[2];
return socket(domain, type, protocol);
int sockfd = socket(domain, type, protocol);
if (sockfd >= 0) {
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
}
return sockfd;
}
long native_bind(long *args, int argc) {
@@ -716,6 +904,137 @@ long native_double_div(long *args, int argc) {
return result.l;
}
long native_async_fread(long *args, int argc) {
if (!args || argc < 3) return -1;
FILE *f = (FILE*)args[0];
int addr = (int)args[1];
int size = (int)args[2];
if (!f || addr < 0 || addr >= MEM_SIZE || size <= 0) return -1;
int id = alloc_async_op();
if (id < 0) return -1;
AsyncFileReadData *data = malloc(sizeof(AsyncFileReadData));
data->f = f;
data->addr = addr;
data->size = size;
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_fread_thread, id_ptr);
return id;
}
long native_async_fwrite(long *args, int argc) {
if (!args || argc < 3) return -1;
FILE *f = (FILE*)args[0];
long buf_arg = args[1];
int size = (int)args[2];
if (!f || size <= 0) return -1;
int id = alloc_async_op();
if (id < 0) return -1;
AsyncFileWriteData *data = malloc(sizeof(AsyncFileWriteData));
data->f = f;
data->buf_arg = buf_arg;
data->size = size;
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_fwrite_thread, id_ptr);
return id;
}
long native_async_recv(long *args, int argc) {
if (!args || argc < 4) return -1;
int sockfd = (int)args[0];
int addr = (int)args[1];
int len = (int)args[2];
int flags = (int)args[3];
if (addr < 0 || addr >= MEM_SIZE) return -1;
int id = alloc_async_op();
if (id < 0) return -1;
AsyncRecvData *data = malloc(sizeof(AsyncRecvData));
data->sockfd = sockfd;
data->addr = addr;
data->len = len;
data->flags = flags;
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_recv_thread, id_ptr);
return id;
}
long native_async_send(long *args, int argc) {
if (!args || argc < 4) return -1;
int sockfd = (int)args[0];
long buf_arg = args[1];
int len = (int)args[2];
int flags = (int)args[3];
int id = alloc_async_op();
if (id < 0) return -1;
AsyncSendData *data = malloc(sizeof(AsyncSendData));
data->sockfd = sockfd;
data->buf_arg = buf_arg;
data->len = len;
data->flags = flags;
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_send_thread, id_ptr);
return id;
}
long native_async_wait(long *args, int argc) {
if (!args || argc < 1) return -1;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
pthread_join(async_ops[id].thread, NULL);
pthread_mutex_lock(&async_mutex);
long result = async_ops[id].result;
async_ops[id].active = 0;
pthread_mutex_unlock(&async_mutex);
return result;
}
long native_async_poll(long *args, int argc) {
if (!args || argc < 1) return 0;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return 0;
pthread_mutex_lock(&async_mutex);
int complete = async_ops[id].complete;
pthread_mutex_unlock(&async_mutex);
return complete;
}
long native_async_result(long *args, int argc) {
if (!args || argc < 1) return -1;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
pthread_mutex_lock(&async_mutex);
long result = async_ops[id].result;
async_ops[id].active = 0;
pthread_mutex_unlock(&async_mutex);
return result;
}
void register_native_functions() {
register_native_func("socket", native_socket);
register_native_func("bind", native_bind);
@@ -763,4 +1082,11 @@ void register_native_functions() {
register_native_func("double_sub", native_double_sub);
register_native_func("double_mul", native_double_mul);
register_native_func("double_div", native_double_div);
register_native_func("async_fread", native_async_fread);
register_native_func("async_fwrite", native_async_fwrite);
register_native_func("async_recv", native_async_recv);
register_native_func("async_send", native_async_send);
register_native_func("async_wait", native_async_wait);
register_native_func("async_poll", native_async_poll);
register_native_func("async_result", native_async_result);
}