/** * An implementation for a message pipe system as described in * * http://eventuallyconsistent.net/2013/08/14/messaging-as-a-programming-model-part-2/ * * A message is passed through a series of filter routines which do things. * * Rather then loops I try using recursion here. * * copyright: GPL Copyleft * * Mark Koennecke, November 2013 */ #include #include #include #include /*--------------------------------------------------------------------------------*/ typedef struct __MessagePipe { void *userData; mpUserKill killFunc; mpFilterFunc filterFunc; struct __MessagePipe *next; struct __MessagePipe *previous; } MessagePipe; /*--------------------------------------------------------------------------------*/ static int EmptyFunc(void *message, void *userData) { return MPCONTINUE; } /*---------------------------------------------------------------------------------*/ pMP MakeMP() { pMP result = NULL; result = malloc(sizeof(MessagePipe)); if(result != NULL){ memset(result,0,sizeof(MessagePipe)); result->filterFunc = EmptyFunc; } return result; } /*---------------------------------------------------------------------------------*/ void KillMP(pMP self) { if(self == NULL){ return; } pMP next = self->next; if(self->userData != NULL && self->killFunc != NULL){ self->killFunc(self->userData); } free(self); KillMP(next); } /*-----------------------------------------------------------------------------------*/ int AppendMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill) { assert(self != NULL); assert(func != NULL); if(self->next == NULL){ self->next = malloc(sizeof(MessagePipe)); if(self->next != NULL){ self->next->previous = self; self->next->next = NULL; self->next->userData = userData; self->next->killFunc = usKill; self->next->filterFunc = func; return 0; } else { return 1; } } else { return AppendMPFilter(self->next, func, userData, usKill); } } /*-----------------------------------------------------------------------------------*/ pMP PrependMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill) { pMP result = NULL; assert(func != NULL); result = malloc(sizeof(MessagePipe)); if(result != NULL){ result->userData = userData; result->killFunc = usKill; result->filterFunc = func; result->next = self; result->previous = NULL; return result; } else { /* we are ignoring an error here......... */ return self; } } /*-----------------------------------------------------------------------------------*/ int MPprocess(pMP self, void *message) { int status; if(self == NULL || self->filterFunc == NULL){ return MPCONTINUE; } else { status = self->filterFunc(message, self->userData); if(status == MPSTOP){ return status; } else { return MPprocess(self->next, message); } } }