summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-04-26 15:16:56 +0200
committerAndreas Baumann <abaumann@yahoo.com>2009-04-26 15:16:56 +0200
commitefbc5946bf6a8126ffaeea7a0abf54b29d3c572a (patch)
tree408a2da35957ee483ec689c92869c082d2237a2a /tests
parent57898d7986de91792d725e2c4c1e648aa90dec43 (diff)
downloadwolfbones-efbc5946bf6a8126ffaeea7a0abf54b29d3c572a.tar.gz
wolfbones-efbc5946bf6a8126ffaeea7a0abf54b29d3c572a.tar.bz2
added a proactor test, trying to implement the paper on Linux with
something like epoll
Diffstat (limited to 'tests')
-rw-r--r--tests/network/test_proactor.c205
1 files changed, 205 insertions, 0 deletions
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 <sys/types.h> /* 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;
+}
+