From efbc5946bf6a8126ffaeea7a0abf54b29d3c572a Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 26 Apr 2009 15:16:56 +0200 Subject: added a proactor test, trying to implement the paper on Linux with something like epoll --- tests/network/test_proactor.c | 205 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 tests/network/test_proactor.c (limited to 'tests') diff --git a/tests/network/test_proactor.c b/tests/network/test_proactor.c new file mode 100644 index 0000000..fc44b13 --- /dev/null +++ b/tests/network/test_proactor.c @@ -0,0 +1,205 @@ +/* Trying to implement a simplistic asynch I/O system using the Proactor + Connector/Acceptor pattern. Unix-only at the moment. Trying to get the + C APIs right + */ + +/* INTERFACE */ + +#include "errors.h" + +#include "port/unused.h" + +#include /* for size_t */ + +typedef struct wolf_asio_proc_t *wolf_asio_proc_p; +typedef struct wolf_asio_completion_dispatcher_t *wolf_asio_completion_dispatcher_p; + +/* Completion Handler: they are implemented in the Proactive Initiator, in + * this case: + * - the Acceptor: accepts new connections arsynchronously + * - the Protocol Handler: handles all the communication with the + * other peer, it should never do long synchronous work! + */ +typedef void(*wolf_asio_completion_handler_f)( void ); + +/* Asynchronous Operation Processor (asio_proc): + * - performs the asynchronous opreation on behalf of the application, + * usually with a lot of help from the operating system + * - must NOT seize control of the callers thread! + * - if we miss asynchronous OS calls, we must emulate them with a + * pool of dedicated threads which poll the OS + */ + +typedef struct wolf_asio_proc_t { + wolf_asio_completion_dispatcher_p completion_dispatcher; +} wolf_asio_proc_t; + +wolf_asio_proc_p wolf_asio_proc_new( wolf_asio_completion_dispatcher_p completion_dispatcher, + wolf_error_t *error ); + +wolf_error_t wolf_asio_proc_free( wolf_asio_proc_p proc ); + +/* + * Asynchronous Operations: + * - the asynchronous operation must be performed without using + * the applications thread! + * - when an asynchronous operations completes (as compared to the + * reactor pattern, where the actual OS operation is still done + * by the application!), the asio_proc deletegates the notification + * of the appliation to the Completion Distpatcher + */ + +wolf_error_t wolf_asio_proc_write( wolf_asio_proc_p proc, + char *buf, + size_t buflen ); + +wolf_error_t wolf_asio_proc_read( wolf_asio_proc_p proc, + char *buf, + size_t buflen ); + +wolf_error_t wolf_asio_proc_accept( wolf_asio_proc_p proc, + wolf_asio_completion_handler_f completion_handler ); + +/** + * Acceptor + * - decouples normal operation in active connections from new + * connections + * - asks the async operation processor + */ + +/* Asynchronous Completion Token: + * - stores state information to complete the asynchronous request, partial + * reads/writes (filehandle, position) + */ + +/* TODO: opening files and pipes should be immediate, what about connect/accept? */ + +/* Completion Dispatcher: + * - on completion it has to call the registerd completion_handler + * - dispatch concurrency strategy: + * - signal the completion as conditional/event to the rendevous point of the + * application thread + * - borrow the thread + * - pool of dedicated threads + * - there is a notification queue which gets processed by the completion + * dispatcher + */ + +typedef struct wolf_asio_completion_dispatcher_t { + int dummy; +} wolf_asio_completion_dispatcher_t; + +wolf_asio_completion_dispatcher_p wolf_asio_completion_dispatcher_new( wolf_error_t *error ); + +wolf_error_t wolf_asio_completion_dispatcher_free( wolf_asio_completion_dispatcher_p dispatcher ); + +wolf_error_t wolf_asio_completion_dispatcher_dispatch( wolf_asio_completion_dispatcher_p dispatcher ); + +/* IMPLEMENTATION */ + +#include "port/stdlib.h" /* for EXIT_XX, NULL, malloc, free */ + +wolf_asio_proc_p wolf_asio_proc_new( wolf_asio_completion_dispatcher_p completion_dispatcher, + wolf_error_t *error ) { + wolf_asio_proc_p proc; + + proc = (wolf_asio_proc_p)malloc( sizeof( struct wolf_asio_proc_t ) ); + if( proc == NULL ) { + *error = WOLF_ERR_OUT_OF_MEMORY; + return NULL; + } + + proc->completion_dispatcher = completion_dispatcher; + return proc; +} + +wolf_error_t wolf_asio_proc_free( wolf_asio_proc_p proc ) { + if( proc == NULL ) { + return WOLF_ERR_INVALID_STATE; + } + + free( proc ); + proc = NULL; + + return WOLF_OK; +} + +wolf_error_t wolf_asio_proc_accept( wolf_asio_proc_p proc, + wolf_asio_completion_handler_f completion_handler ) { + WOLF_UNUSED( proc ); + WOLF_UNUSED( completion_handler ); + + /* start an aynchronous accept */ + /* call completion_handler in the contect of the completion_dispatcher on completion */ + + return WOLF_OK; +} + +wolf_asio_completion_dispatcher_p wolf_asio_completion_dispatcher_new( wolf_error_t *error ) { + wolf_asio_completion_dispatcher_p dispatcher; + + dispatcher = (wolf_asio_completion_dispatcher_p)malloc( sizeof( struct wolf_asio_completion_dispatcher_t ) ); + if( dispatcher == NULL ) { + *error = WOLF_ERR_OUT_OF_MEMORY; + return NULL; + } + + return dispatcher; +} + +wolf_error_t wolf_asio_completion_dispatcher_free( wolf_asio_completion_dispatcher_p dispatcher ) { + if( dispatcher == NULL ) { + return WOLF_ERR_INVALID_STATE; + } + + free( dispatcher ); + dispatcher = NULL; + + return WOLF_OK; +} + +/* completion handlers */ + +static void accept_handler( void ) { +} + +/* MAIN, the proactive initiator + * + */ + +int main( void ) { + wolf_asio_proc_p proc; + wolf_asio_completion_dispatcher_p dispatcher; + wolf_error_t error; + + dispatcher = wolf_asio_completion_dispatcher_new( &error ); + if( dispatcher == NULL ) { + return EXIT_FAILURE; + } + + proc = wolf_asio_proc_new( dispatcher, &error ); + if( proc == NULL ) { + (void)wolf_asio_completion_dispatcher_free( dispatcher ); + return EXIT_FAILURE; + } + + /* loop and wait for clients connecting */ + while( 1 ) { + error = wolf_asio_proc_accept( proc, accept_handler ); + if( error != WOLF_OK ) { + (void)wolf_asio_completion_dispatcher_free( dispatcher ); + (void)wolf_asio_proc_free( proc ); + return EXIT_FAILURE; + } + } + + if( wolf_asio_proc_free( proc ) != WOLF_OK ) { + return EXIT_FAILURE; + } + if( wolf_asio_completion_dispatcher_free( dispatcher ) != WOLF_OK ) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + -- cgit v1.2.3-54-g00ecf