This is a short guide to creating a notify call list which is useful for sending message across an entire program which can work dynamically. The clasic example of these is when a program is about to exit. This can give everything a chance to attach to events like this then handle the outcome.
For this particular example it uses a C++ template to create a class which will be able to Add / Remove or Call the list. Which will accept a basic type with a custom argument.
template <class T, class P>
class Notify {
class NotifyItem {
public:
void (*m_fp) (T, P);
P m_priv;
};
private:
std::list<NotifyItem> m_list;
public:
void Add(void (*fp) (T, P), P priv) {
#ifdef DEBUG
//Check for existing item in debug mode
typename std::list<NotifyItem>::iterator x;
for(x = m_list.begin(); x != m_list.end(); x++) {
if (x->m_fp == fp && x->m_priv == priv)
abort();
}
#endif
NotifyItem tmp;
tmp.m_fp = fp;
tmp.m_priv = priv;
m_list.push_back(tmp);
}
void Remove(void (*fp) (T, P), P priv) {
typename std::list<NotifyItem>::iterator x;
for(x = m_list.begin(); x != m_list.end(); x++) {
if (x->m_fp == fp && x->m_priv == priv) {
m_list.erase(x);
return;
}
}
}
void Call(T arg) {
typename std::list<NotifyItem>::iterator x;
for(x = m_list.begin(); x != m_list.end(); x++) {
x->m_fp(arg, x->m_priv);
}
}
};
A short example of how to use the template above to pass two int's to a function. As you can see it is quite simple to use. You could of course pass other arguments types or make the functions very generic using something like Notify<int, void *> or pass an interface type class for handling the events.
void func(int arg, int priv) {
printf("%d %d\n", arg, priv);
}
int main(int argc, char **argv) {
Notify<int, int> inotify;
inotify.Add(func, 10);
inotify.Add(func, 11);
inotify.Add(func, 12);
inotify.Add(func, 13);
inotify.Remove(func, 12);
inotify.Call(0);
printf("Finished\n");
return 0;
}