From 99a8dbc12c1b61eecb798c1cb0fa2044c3344c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sun, 14 Apr 2013 20:40:07 +0000 Subject: simple notification abstraction last implementation used another thread that called clock_set() in a sys_lock(). this implementation uses a pipe and sys_addpollfn() svn path=/trunk/externals/iem/iemnet/; revision=17089 --- iemnet.h | 30 ++++++++++++++ iemnet_notify.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 iemnet_notify.c diff --git a/iemnet.h b/iemnet.h index 93204cf..9ee1394 100644 --- a/iemnet.h +++ b/iemnet.h @@ -149,6 +149,36 @@ void iemnet__receiver_destroy(t_iemnet_receiver*); int iemnet__receiver_getsize(t_iemnet_receiver*); +/** + * opaque data type used for a notification server + */ +typedef struct _iemnet_notifier t_iemnet_notifier; +EXTERN_STRUCT _iemnet_notifier; +t_iemnet_notifier*iemnet__notify_create(void); +void iemnet__notify_destroy(t_iemnet_notifier*x); + +/** + * opaque data type used for a notification client + */ +typedef struct _iemnet_notify t_iemnet_notify; +EXTERN_STRUCT _iemnet_notify; +void iemnet__notify_remove(t_iemnet_notify*notify); +/** + * callback function from main thread on notification + */ +typedef void (*t_iemnet_notifun)(void *data); +/** + * register a new notification callback with the 'notifier' server. + * on success, returns a notification client to be passed to iemnet__notify() + * on failure, returns NULL + */ +t_iemnet_notify*iemnet__notify_add(t_iemnet_notifier*notifier, t_iemnet_notifun fun, void*data); +/** + * tell mainthread that something happened with 'notify' client + * (will call the callback associated to 'notify' asap) + */ +void iemnet__notify(t_iemnet_notify*notify); + /* convenience functions */ diff --git a/iemnet_notify.c b/iemnet_notify.c new file mode 100644 index 0000000..aea1048 --- /dev/null +++ b/iemnet_notify.c @@ -0,0 +1,122 @@ +/* iemnet + * + * notify + * notifies mai thread that new data has arrived + * + * copyright (c) 2012 IOhannes m zmölnig, IEM + */ + +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., */ +/* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* */ + +#define DEBUGLEVEL 4 + +#include "iemnet.h" +#include "iemnet_data.h" + +/* for pipe() */ +#include + +/* for printf() debugging */ +#include + +typedef struct _iemnet_notify{ + void*data; + t_iemnet_notifun fun; + struct _iemnet_notifier*parent; + struct _iemnet_notify*next; +} t_iemnet_notify; + +static t_iemnet_notify*pollqueue=NULL; + +typedef struct _iemnet_notifier { + int fd[2]; + struct _iemnet_notify*nodes; +} t_iemnet_notifier; + +static t_iemnet_notifier *masternotifier = NULL; + +/* notifies Pd that there is new data to fetch */ +void iemnet__notify(t_iemnet_notify*x) { + write(masternotifier->fd[1], x, sizeof(x)); +} + +static void pollfun(void*x, int fd) { + char buf[4096]; + int result=-1; + t_iemnet_notify*q; + result=read(fd, buf, sizeof(buf)); + for(q=pollqueue; q; q=q->next) { + (q->fun)(q->data); + } +} + +static void iemnet__notifier_print(t_iemnet_notifier*x) { + t_iemnet_notify*q; + for(q=pollqueue; q; q=q->next) { + printf("queue[%p]={fun:%p, data:%p, next:%p}\n", q, q->fun, q->data, q->next); + } +} +t_iemnet_notifier*iemnet__notify_create(void) { + if(masternotifier!=NULL) + return masternotifier; + masternotifier=(t_iemnet_notifier*)getbytes(sizeof(t_iemnet_notifier)); + post("adding new poller"); + if(!pipe(masternotifier->fd)) { + post("POLL %d/%d", masternotifier->fd[0], masternotifier->fd[1]); + sys_addpollfn(masternotifier->fd[0], pollfun, masternotifier); + return masternotifier; + } + return NULL; +} +void iemnet__notify_destroy(t_iemnet_notifier*x) { + // nada +} + +t_iemnet_notify*iemnet__notify_add(t_iemnet_notifier*notifier, t_iemnet_notifun fun, void*data) { + /* add the given receiver to the poll-queue + * LATER: check whether it's already in there... + */ + t_iemnet_notify*q=(t_iemnet_notify*)getbytes(sizeof(t_iemnet_notify)); + q->fun =fun; + q->data=data; + q->parent=notifier; + q->next=pollqueue; + pollqueue=q; + iemnet__notifier_print(notifier); + return q; +} +void iemnet__notify_remove(t_iemnet_notify*x) { + t_iemnet_notify*q=pollqueue; + t_iemnet_notify*last=NULL; + iemnet__notifier_print(q->parent); + + for(q=pollqueue; q; q=q->next) { + if(q == x) { + if(last) { + last->next=q->next; + } else { + pollqueue=q->next; + } + q->fun =NULL; + q->data=NULL; + q->next=NULL; + freebytes(q, sizeof(*q)); + return; + } + last=q; + } +} -- cgit v1.2.1