Async implementation.
This commit is contained in:
parent
050e85b72a
commit
5828aa8622
29
Makefile
29
Makefile
@ -25,11 +25,16 @@ TESTS = $(TEST_DIR)/feature_test.rc \
|
||||
$(TEST_DIR)/math_test.rc \
|
||||
$(TEST_DIR)/string_test.rc \
|
||||
$(TEST_DIR)/string_manip_test.rc \
|
||||
$(TEST_DIR)/increment_decrement_test.rc
|
||||
$(TEST_DIR)/increment_decrement_test.rc \
|
||||
$(TEST_DIR)/file_io_test.rc \
|
||||
$(TEST_DIR)/double_test.rc \
|
||||
$(TEST_DIR)/break_continue_test.rc \
|
||||
$(TEST_DIR)/async_io_test.rc
|
||||
|
||||
EXAMPLES = $(EXAMPLE_DIR)/http_simple.rc \
|
||||
$(EXAMPLE_DIR)/http_persistent.rc \
|
||||
$(EXAMPLE_DIR)/http_multi.rc
|
||||
$(EXAMPLE_DIR)/http_multi.rc \
|
||||
$(EXAMPLE_DIR)/async_demo.rc
|
||||
|
||||
.PHONY: all clean test run-tests run-examples help
|
||||
|
||||
@ -88,6 +93,18 @@ run-string-manip: $(TARGET)
|
||||
run-increment-decrement-test: $(TARGET)
|
||||
$(TARGET) $(TEST_DIR)/increment_decrement_test.rc
|
||||
|
||||
run-file-io-test: $(TARGET)
|
||||
$(TARGET) $(TEST_DIR)/file_io_test.rc
|
||||
|
||||
run-double-test: $(TARGET)
|
||||
$(TARGET) $(TEST_DIR)/double_test.rc
|
||||
|
||||
run-break-continue-test: $(TARGET)
|
||||
$(TARGET) $(TEST_DIR)/break_continue_test.rc
|
||||
|
||||
run-async-io-test: $(TARGET)
|
||||
$(TARGET) $(TEST_DIR)/async_io_test.rc
|
||||
|
||||
run-http-simple: $(TARGET)
|
||||
$(TARGET) $(EXAMPLE_DIR)/http_simple.rc
|
||||
|
||||
@ -97,6 +114,9 @@ run-http-persistent: $(TARGET)
|
||||
run-http-multi: $(TARGET)
|
||||
$(TARGET) $(EXAMPLE_DIR)/http_multi.rc
|
||||
|
||||
run-async-demo: $(TARGET)
|
||||
$(TARGET) $(EXAMPLE_DIR)/async_demo.rc
|
||||
|
||||
help:
|
||||
@echo "RC - Retoor's C Interpreter"
|
||||
@echo ""
|
||||
@ -111,11 +131,16 @@ help:
|
||||
@echo " make run-math-test - Run math_test.rc (math functions)"
|
||||
@echo " make run-string-test - Run string_test.rc (string concatenation)"
|
||||
@echo " make run-string-manip - Run string_manip_test.rc (string manipulation & slicing)"
|
||||
@echo " make run-file-io-test - Run file_io_test.rc (file I/O operations)"
|
||||
@echo " make run-double-test - Run double_test.rc (double data type)"
|
||||
@echo " make run-break-continue-test - Run break_continue_test.rc (break/continue)"
|
||||
@echo " make run-async-io-test - Run async_io_test.rc (async I/O)"
|
||||
@echo ""
|
||||
@echo "Examples:"
|
||||
@echo " make run-http-simple - Run http_simple.rc (single connection HTTP server)"
|
||||
@echo " make run-http-persistent - Run http_persistent.rc (persistent HTTP server)"
|
||||
@echo " make run-http-multi - Run http_multi.rc (HTTP server, 100 connections)"
|
||||
@echo " make run-async-demo - Run async_demo.rc (comprehensive async I/O demo)"
|
||||
@echo ""
|
||||
@echo "Directory Structure:"
|
||||
@echo " src/ - Source code files"
|
||||
|
||||
34
README.md
34
README.md
@ -8,6 +8,7 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
||||
|
||||
**Data Types**
|
||||
- Integers (long)
|
||||
- Doubles (floating-point numbers)
|
||||
- Character pointers (char*)
|
||||
- Pointer operations (address-of &, dereference *)
|
||||
- Array declarations and indexing
|
||||
@ -15,6 +16,7 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
||||
**Control Flow**
|
||||
- if/else statements
|
||||
- while loops (including infinite loops)
|
||||
- break and continue statements
|
||||
- Comparison operators: ==, !=, <, >, <=, >=
|
||||
- Logical operators: &&, ||
|
||||
|
||||
@ -39,6 +41,13 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
||||
- sin(x), cos(x), tan(x) - Trigonometric functions
|
||||
- floor(x), ceil(x) - Rounding functions
|
||||
|
||||
**Double Type Functions**
|
||||
- int_to_double(i) - Convert int to double
|
||||
- double_to_int(d) - Convert double to int
|
||||
- double_add(a, b), double_sub(a, b) - Double arithmetic
|
||||
- double_mul(a, b), double_div(a, b) - Double arithmetic
|
||||
- printf with %f format for doubles
|
||||
|
||||
**String Functions**
|
||||
- strpos(haystack, needle) - Find substring position
|
||||
- substr(str, start, length) - Extract substring
|
||||
@ -49,6 +58,27 @@ RC is a lightweight, recursive-descent C interpreter written in C. It executes a
|
||||
- endswith(str, suffix) - Suffix check
|
||||
- strlen(str) - String length
|
||||
|
||||
**File I/O**
|
||||
- fopen(filename, mode) - Open a file
|
||||
- fclose(file) - Close a file
|
||||
- fread(file, buffer, size) - Read from file
|
||||
- fwrite(file, buffer, size) - Write to file
|
||||
- fgets(file, max_size) - Read a line
|
||||
- fputs(file, string) - Write a string
|
||||
- feof(file) - Check end of file
|
||||
- ftell(file), fseek(file, offset, whence) - File positioning
|
||||
- fremove(filename), frename(old, new) - File operations
|
||||
- SEEK_SET, SEEK_CUR, SEEK_END constants
|
||||
|
||||
**Async I/O (Multi-threaded)**
|
||||
- async_fread(file, buffer, size) - Async file read
|
||||
- async_fwrite(file, buffer, size) - Async file write
|
||||
- async_recv(socket, buffer, len, flags) - Async socket receive
|
||||
- async_send(socket, buffer, len, flags) - Async socket send
|
||||
- async_wait(handle) - Wait for async operation to complete
|
||||
- async_poll(handle) - Check if async operation is complete
|
||||
- async_result(handle) - Get result of completed async operation
|
||||
|
||||
**Socket Programming**
|
||||
- socket(), bind(), listen(), accept()
|
||||
- send(), recv(), close()
|
||||
@ -169,10 +199,12 @@ Extensible system for binding C functions. Current bindings include math operati
|
||||
|
||||
- Memory model uses long cells (not byte-accurate)
|
||||
- No support for structs, unions, or enums as user types
|
||||
- Limited type system (int and char* only)
|
||||
- Limited type system (int, double, and char*)
|
||||
- Double arithmetic requires explicit helper functions
|
||||
- No preprocessor directives
|
||||
- Error messages show token index rather than line/column
|
||||
- Pointer arithmetic works on virtual memory addresses
|
||||
- Maximum 100 concurrent async operations
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
171
TUTORIAL.md
171
TUTORIAL.md
@ -986,3 +986,174 @@ int main() {
|
||||
---
|
||||
|
||||
For more examples, see the `tests/` and `examples/` directories in the RC repository.
|
||||
|
||||
## File I/O
|
||||
|
||||
### Writing to a File
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int f = fopen("output.txt", "w");
|
||||
fputs(f, "Hello, File!\n");
|
||||
fputs(f, "Second line\n");
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Reading from a File
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int f = fopen("output.txt", "r");
|
||||
char *line = fgets(f, 256);
|
||||
while (strlen(line) > 0 && feof(f) == 0) {
|
||||
printf("%s", line);
|
||||
line = fgets(f, 256);
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Double Data Type
|
||||
|
||||
### Using Doubles
|
||||
|
||||
```c
|
||||
int main() {
|
||||
double pi = 3.14159;
|
||||
double radius = 5.0;
|
||||
|
||||
printf("Pi: %f\n", pi);
|
||||
printf("Radius: %f\n", radius);
|
||||
|
||||
double area = double_mul(pi, double_mul(radius, radius));
|
||||
printf("Circle area: %f\n", area);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Type Conversions
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int x = 42;
|
||||
double dx = int_to_double(x);
|
||||
printf("Int %d as double: %f\n", x, dx);
|
||||
|
||||
double y = 99.9;
|
||||
int iy = double_to_int(y);
|
||||
printf("Double %f as int: %d\n", y, iy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Break and Continue
|
||||
|
||||
### Break Statement
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int i = 0;
|
||||
while (i < 10) {
|
||||
i = i + 1;
|
||||
if (i == 5) {
|
||||
printf("Breaking at %d\n", i);
|
||||
break;
|
||||
}
|
||||
printf("%d ", i);
|
||||
}
|
||||
printf("\nDone\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Continue Statement
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int i = 0;
|
||||
while (i < 10) {
|
||||
i = i + 1;
|
||||
if (i == 3 || i == 7) {
|
||||
continue;
|
||||
}
|
||||
printf("%d ", i);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Async I/O
|
||||
|
||||
### Async File Operations
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int f = fopen("async_file.txt", "w");
|
||||
|
||||
int write_handle = async_fwrite(f, "Async write!", 12);
|
||||
printf("Write started, handle: %d\n", write_handle);
|
||||
|
||||
int result = async_wait(write_handle);
|
||||
printf("Write completed, bytes: %d\n", result);
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Polling for Completion
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int f = fopen("data.txt", "r");
|
||||
int buffer[1024];
|
||||
|
||||
int read_handle = async_fread(f, &buffer, 1024);
|
||||
|
||||
printf("Reading asynchronously...\n");
|
||||
while (async_poll(read_handle) == 0) {
|
||||
printf(".");
|
||||
}
|
||||
printf("\nRead complete!\n");
|
||||
|
||||
int bytes = async_result(read_handle);
|
||||
printf("Bytes read: %d\n", bytes);
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Async Socket I/O
|
||||
|
||||
```c
|
||||
int main() {
|
||||
int server = socket(AF_INET(), SOCK_STREAM(), 0);
|
||||
bind(server, 8080);
|
||||
listen(server, 5);
|
||||
|
||||
int client = accept(server);
|
||||
|
||||
int buffer[1024];
|
||||
int recv_handle = async_recv(client, &buffer, 1024, 0);
|
||||
|
||||
printf("Async receive started...\n");
|
||||
int bytes = async_wait(recv_handle);
|
||||
printf("Received %d bytes\n", bytes);
|
||||
|
||||
char *response = "HTTP/1.1 200 OK\r\n\r\nOK";
|
||||
int send_handle = async_send(client, response, strlen(response), 0);
|
||||
async_wait(send_handle);
|
||||
|
||||
close(client);
|
||||
close(server);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
86
examples/async_demo.rc
Normal file
86
examples/async_demo.rc
Normal file
@ -0,0 +1,86 @@
|
||||
int main() {
|
||||
printf("=== Async I/O Demo: File I/O + Async I/O + Socket I/O ===\n\n");
|
||||
|
||||
printf("Step 1: Synchronous File I/O\n");
|
||||
int log_file = fopen("demo_log.txt", "w");
|
||||
fputs(log_file, "Server Log Started\n");
|
||||
fclose(log_file);
|
||||
printf("Created log file\n\n");
|
||||
|
||||
printf("Step 2: Async File Operations\n");
|
||||
log_file = fopen("demo_log.txt", "a");
|
||||
int write_op1 = async_fwrite(log_file, "Initializing server...\n", 24);
|
||||
int write_op2 = async_fwrite(log_file, "Binding to port 8080...\n", 25);
|
||||
|
||||
printf("Multiple async writes queued\n");
|
||||
async_wait(write_op1);
|
||||
async_wait(write_op2);
|
||||
printf("All async writes completed\n\n");
|
||||
|
||||
printf("Step 3: Socket Server Setup\n");
|
||||
int server_socket = socket(AF_INET(), SOCK_STREAM(), 0);
|
||||
if (server_socket < 0) {
|
||||
printf("ERROR: Could not create socket\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Socket created: %d\n", server_socket);
|
||||
|
||||
int bind_result = bind(server_socket, 8080);
|
||||
if (bind_result < 0) {
|
||||
printf("ERROR: Could not bind to port\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Bound to port 8080\n");
|
||||
|
||||
listen(server_socket, 5);
|
||||
printf("Listening for connections...\n\n");
|
||||
|
||||
printf("Step 4: Log async write while waiting for connection\n");
|
||||
int log_op = async_fwrite(log_file, "Waiting for client...\n", 23);
|
||||
|
||||
printf("Accepting client (this will wait for a connection)\n");
|
||||
printf("In another terminal, run: curl http://localhost:8080/\n\n");
|
||||
|
||||
int client = accept(server_socket);
|
||||
async_wait(log_op);
|
||||
printf("Client connected: %d\n\n", client);
|
||||
|
||||
printf("Step 5: Handle client with async socket I/O\n");
|
||||
int buffer[1024];
|
||||
int recv_op = async_recv(client, &buffer, 1024, 0);
|
||||
|
||||
printf("Async receive started...\n");
|
||||
while (async_poll(recv_op) == 0) {
|
||||
printf(".");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
int bytes = async_result(recv_op);
|
||||
printf("Received %d bytes\n", bytes);
|
||||
|
||||
char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nAsync I/O Demo Success!\n";
|
||||
int send_op = async_send(client, response, strlen(response), 0);
|
||||
async_wait(send_op);
|
||||
printf("Response sent asynchronously\n\n");
|
||||
|
||||
printf("Step 6: Final log entry\n");
|
||||
int final_log = async_fwrite(log_file, "Client served successfully\n", 28);
|
||||
async_wait(final_log);
|
||||
|
||||
close(client);
|
||||
close(server_socket);
|
||||
fclose(log_file);
|
||||
|
||||
printf("\nStep 7: Read log file\n");
|
||||
log_file = fopen("demo_log.txt", "r");
|
||||
char *line = fgets(log_file, 256);
|
||||
while (strlen(line) > 0 && feof(log_file) == 0) {
|
||||
printf("LOG: %s", line);
|
||||
line = fgets(log_file, 256);
|
||||
}
|
||||
fclose(log_file);
|
||||
|
||||
printf("\n=== Demo Complete ===\n");
|
||||
printf("Demonstrated: Sync File I/O, Async File I/O, Socket I/O, and Async Socket I/O\n");
|
||||
return 0;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
44
tests/async_io_test.rc
Normal file
44
tests/async_io_test.rc
Normal file
@ -0,0 +1,44 @@
|
||||
int main() {
|
||||
printf("=== Async I/O Tests ===\n");
|
||||
|
||||
printf("Test 1: Async file write\n");
|
||||
int f = fopen("async_test.txt", "w");
|
||||
if (f == 0) {
|
||||
printf("ERROR: Could not open file\n");
|
||||
return 1;
|
||||
}
|
||||
int write_handle = async_fwrite(f, "Hello from async I/O!", 21);
|
||||
printf("Write started, handle: %d\n", write_handle);
|
||||
int result = async_wait(write_handle);
|
||||
printf("Write completed, bytes written: %d\n", result);
|
||||
fclose(f);
|
||||
printf("PASS: Async write works\n");
|
||||
|
||||
printf("Test 2: Async file read\n");
|
||||
f = fopen("async_test.txt", "r");
|
||||
if (f == 0) {
|
||||
printf("ERROR: Could not open file\n");
|
||||
return 1;
|
||||
}
|
||||
int buffer[256];
|
||||
int read_handle = async_fread(f, &buffer, 256);
|
||||
printf("Read started, handle: %d\n", read_handle);
|
||||
|
||||
printf("Polling for completion...\n");
|
||||
while (async_poll(read_handle) == 0) {
|
||||
printf(".");
|
||||
}
|
||||
printf("\nRead complete!\n");
|
||||
|
||||
result = async_result(read_handle);
|
||||
printf("Bytes read: %d\n", result);
|
||||
fclose(f);
|
||||
printf("PASS: Async read works\n");
|
||||
|
||||
printf("Test 3: Cleanup\n");
|
||||
fremove("async_test.txt");
|
||||
printf("PASS: File removed\n");
|
||||
|
||||
printf("\n=== All Async I/O Tests Completed ===\n");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user