├── .gitignore ├── src ├── asyncio.h ├── queue.c └── asyncio.c ├── README.md └── example.c /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.a 3 | *.o 4 | *.out 5 | 6 | -------------------------------------------------------------------------------- /src/asyncio.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef ASYNC_IO 7 | #define ASYNC_IO 8 | 9 | pthread_t fopen_t(void *(*callback)(FILE *), const char *, const char *); 10 | pthread_t fscanf_t(void *(*callback) (int), FILE *stream, const char *format, ...); 11 | pthread_t fprintf_t(void *(*callback) (int), FILE *stream, const char *format, ...); 12 | pthread_t fclose_t(void *(*callback) (int), FILE *stream); 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Async I/O 2 | 3 | This is a small minimalist library that wraps the standard C I/O functions for non-blocking I/O, providing a high-performance alternative. This was done as an experiment to see if JS programming style can be brought to C programming. Well, the answer is yes! 4 | 5 | The detailed API can be found on the [wiki page](https://github.com/sankha93/async-io/wiki/API). 6 | 7 | ## Building 8 | 9 | Just execute: 10 | 11 | build.sh 12 | 13 | The library will be built as `lib/libasyncio.a`. 14 | 15 | ## Example 16 | 17 | Try the `example.c` file. To compile execute: 18 | 19 | gcc -o example example.c -pthread lib/libasyncio.a 20 | ./example 21 | 22 | ## Make it better 23 | 24 | Sure! Just fork and send a pull request. 25 | -------------------------------------------------------------------------------- /example.c: -------------------------------------------------------------------------------- 1 | #include "src/asyncio.h" 2 | 3 | void fopen_callback(FILE *); 4 | void fprintf_callback(int); 5 | 6 | int main() { 7 | pthread_t thread = fopen_t(&fopen_callback, "test.txt", "w"); 8 | pthread_join(thread, NULL); 9 | } 10 | 11 | void fopen_callback(FILE *stream) { 12 | if (stream != NULL) { 13 | printf("File Opened\n"); 14 | pthread_t thread = fprintf_t(&fprintf_callback, stream, "%s", "Hello World!\n"); 15 | // do any other longer tasks here 16 | // in case all other tasks have finished wait for the I/O to complete 17 | pthread_join(thread, NULL); 18 | } else 19 | printf("Error\n"); 20 | } 21 | 22 | void fprintf_callback(int result) { 23 | if (result > 0) { 24 | printf("File Written\n"); 25 | } else 26 | printf("Error\n"); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct queue { 6 | int capacity; 7 | int size; 8 | int front; 9 | int rear; 10 | pthread_t *elements; 11 | } queue; 12 | 13 | queue *create_queue(int maxElements) { 14 | queue *q = (queue *)malloc(sizeof(queue)); 15 | q -> elements = (int *)malloc(sizeof(pthread_t) * maxElements); 16 | q -> size = 0; 17 | q -> capacity = 0; 18 | q -> front = 0; 19 | q -> rear = -1; 20 | return q; 21 | } 22 | 23 | void dequeue(queue *q) { 24 | if (q -> size != 0) { 25 | q -> size--; 26 | q -> front++; 27 | if (q -> front == q -> capacity) 28 | q -> front = 0; 29 | } 30 | } 31 | 32 | pthread_t front(queue *q) { 33 | if (q -> size != 0) 34 | return q -> elements[q -> front]; 35 | } 36 | 37 | void enqueue(queue *q, pthread_t element) { 38 | if (q -> size == q -> capacity) 39 | q -> capacity++; 40 | else { 41 | q -> size++; 42 | q -> rear = q -> rear + 1; 43 | if (q -> rear == q -> capacity) 44 | q -> rear = 0; 45 | q -> elements[q -> rear] = element; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/asyncio.c: -------------------------------------------------------------------------------- 1 | #include "asyncio.h" 2 | 3 | typedef struct fopen_struct { 4 | char *filename; 5 | char *mode; 6 | void *(*callback) (FILE *); 7 | } fopen_struct; 8 | 9 | typedef struct frw_struct { 10 | FILE *stream; 11 | char *format; 12 | va_list list; 13 | void (*callback) (int); 14 | } frw_struct; 15 | 16 | typedef struct fclose_struct { 17 | FILE *stream; 18 | void *(*callback) (int); 19 | } fclose_struct; 20 | 21 | void *__fclose_t__(fclose_struct *); 22 | void *__fopen_t__(fopen_struct *); 23 | void *__fscanf_t__(frw_struct *); 24 | void *__fprintf_t__(frw_struct *); 25 | 26 | pthread_t fopen_t(void *(*callback)(FILE *), const char *filename, const char *mode) { 27 | fopen_struct *args = (fopen_struct*) malloc(sizeof(fopen_struct)); 28 | args -> filename = filename; 29 | args -> mode = mode; 30 | args -> callback = callback; 31 | pthread_t thread; 32 | pthread_create(&thread, NULL, &__fopen_t__, args); 33 | return thread; 34 | } 35 | 36 | void *__fopen_t__(fopen_struct *ptr) { 37 | fopen_struct *args = (fopen_struct *)ptr; 38 | FILE *result = fopen(args -> filename, args -> mode); 39 | args -> callback(result); 40 | free(args); 41 | } 42 | 43 | pthread_t fclose_t(void *(*callback)(int), FILE *stream) { 44 | fclose_struct *args = (fclose_struct*) malloc(sizeof(fclose_struct)); 45 | args -> stream = stream; 46 | args -> callback = callback; 47 | pthread_t thread; 48 | pthread_create(&thread, NULL, &__fclose_t__, args); 49 | return thread; 50 | } 51 | 52 | void *__fclose_t__(fclose_struct *ptr) { 53 | fclose_struct *args = (fclose_struct *)ptr; 54 | int result = fclose(args -> stream); 55 | args -> callback(result); 56 | free(args); 57 | } 58 | 59 | pthread_t fscanf_t(void *(*callback)(int), FILE *stream, const char *format, ...) { 60 | frw_struct *args = (frw_struct*) malloc(sizeof(frw_struct)); 61 | va_list arguments; 62 | va_start(arguments, *format); 63 | args -> stream = stream; 64 | args -> callback = callback; 65 | args -> list = arguments; 66 | args -> format = format; 67 | pthread_t thread; 68 | pthread_create(&thread, NULL, &__fscanf_t__, args); 69 | return thread; 70 | } 71 | 72 | void *__fscanf_t__(frw_struct *ptr) { 73 | frw_struct *args = (frw_struct *)ptr; 74 | int result = vfscanf(args -> stream, args -> format, args -> list); 75 | args -> callback(result); 76 | free(args); 77 | } 78 | 79 | pthread_t fprintf_t(void *(*callback)(int), FILE *stream, const char *format, ...) { 80 | frw_struct *args = (frw_struct*) malloc(sizeof(frw_struct)); 81 | va_list arguments; 82 | va_start(arguments, *format); 83 | args -> stream = stream; 84 | args -> callback = callback; 85 | args -> list = arguments; 86 | args -> format = format; 87 | pthread_t thread; 88 | pthread_create(&thread, NULL, &__fprintf_t__, args); 89 | return thread; 90 | } 91 | 92 | void *__fprintf_t__(frw_struct *ptr) { 93 | frw_struct *args = (frw_struct *)ptr; 94 | int result = vfprintf(args -> stream, args -> format, args -> list); 95 | args -> callback(result); 96 | free(args); 97 | } 98 | 99 | --------------------------------------------------------------------------------