A callback message has the form
typedef struct { char *class; /* ... message data ... */ } <message class>;where class must be the first element and point to a static variable.
Given the following functions dealing with callbacks:
typedef void KillFunc(void *); typedef int CallbackFunction(Hdb *node, void *msg, void *data); typedef struct Callback Callback; InvokeCallback(Hdb *node, void *msg); Callback *MakeCallback(CallbackFunction *cbFunc, void *data, KillFunc *killFunc); AppendCallback(Hdb *node, Callback *cb); PrependCallback(Hdb *node, Callback *cb);The callbacks are stored as one list per node.
Extract from (sics)hipadaba.h:
typedef struct { char *class; SConnection *pCon; ValueStruct *value; } SetCallbackMsg; SetCallbackMsg *SetCallbackCast(void *msg);
The members of callback message contain the additional arguments needed for the handling of the callback. SetCallbackCast reveals if an anonymous message is a SetCallbackMsg. It returns NULL otherwise.
Extract from (sics)hipadaba.c:
static char *setCallbackClass="set callback"; SetCallbackMsg *SetCallbackCast(void *msg) { if (((SetCallbackMsg *)msg)->class == setCallbackClass) { return msg; } return NULL; } ... /* calling the callback */ SetCallbackMsg setMsg={setCallbackClass}; setMsg.pCon = pCon; setMsg.value = value; InvokeCallback(node, &setMsg);
The text content of setCallbackClass is not very important, it may be used for logging purposes. The check for a particular class is done by comparing the pointers, not the contents.
Extract from a module implementing a callback:
int MySetCallback(Hdb *node, void *msg, void *data) { SetCallbackMsg *setMsg = SetCallbackCast(msg); MyData *mydata; if (! setMsg) return 0; /* not handled */ mydata = data; /* do the set */ return 1; } ... void KillMyData(MyData *data) { /* free resources */ } ... MyData *data; Callback *cb; cb = MakeCallback(MySetCallback, data, (KillFunc *)KillMyData); AppendCallback(node, cb);
An implementation may use the same callback function for handling different callback messages, with the same user data:
int CombinedCallback(Hdb *node, void *msg, void *data) { SetCallbackMsg *setMsg; UpdateCallbackMsg *updateMsg; MyData *mydata = data; setMsg = SetCallbackCast(msg); if (setMsg) { /* handle setMsg */ return 1; } updateMsg= UpdateCallbackCast(msg); if (updateMsg) { /* handle updateMsg */ return 1; } return 0; /* not handled */ }
For the implementation of Hipadaba at least the following callbacks have to be implemented: