Asynchronous IO (async_io/asio)
In programming, the conventional form of handling Input/Output (IO) operations is to issue synchronous (or blocking) IO calls where the program has to wait for the IO operation to finish.
To avoid this, the program could open a thread solely for performing the IO operation, but this comes with typical multithreading issues like overhead and problems like race conditions. Additionally, the programming environment might not have threading capabilities - such as a browser running JavaScript. The alternative is to use asynchronous IO calls, typically provided by the operating system.
Using asynchronous IO makes the most sense when the program is IO-bound.
Example for synchronous IO
#define BUFFER_SIZE 13 char buf[BUFFER_SIZE] = {0}; FILE* fp = fopen("async_io.org", "r"); if (!fp) { /* handle error */ } int ret = fread(buf, 1, BUFFER_SIZE, fp); if (!ret) { /* read failed */ } else { printf("%s\n", buf); } fclose(fp);
Example for asynchronous IO using aio.h
in C
#define BUFFER_SIZE 13 char buf[BUFFER_SIZE]; FILE* fp = fopen("async_io.org", "r"); if (!fp) { /* handle error */ } struct aiocb* aio = malloc(sizeof(struct aiocb)); // asynchronous IO control block if (!aio) { /* handle failed malloc */ } memset(aio, 0, sizeof(*aio)); aio->aio_buf = buf; aio->aio_fildes = fileno(fp); aio->aio_nbytes = BUFFER_SIZE; aio->aio_offset = 0; int result = aio_read(aio); if (result < 0) { /* read failed */ } while(aio_error(aio) == EINPROGRESS) { /* perform operations while async IO is still busy */ } int ret = aio_return(aio); if (!ret) { /* read failed */ } else { printf("%s\n", buf); } fclose(fp);