#include "defs.h" #include "observer.h" typedef void (generic_observer_notification_ftype) (const void *data, const void *args); struct observer { generic_observer_notification_ftype *notify; void *data; /* No memory management needed for this field for now. */ }; struct observer_list { struct observer_list *next; struct observer *observer; }; static struct observer_list * xalloc_observer_list_node (void) { struct observer_list *node = XMALLOC (struct observer_list); node->observer = XMALLOC (struct observer); return node; } static void xfree_observer_list_node (struct observer_list *node) { xfree (node->observer); xfree (node); } static struct observer * generic_observer_attach (struct observer_list **list, generic_observer_notification_ftype *notify, void *data) { struct observer_list *observer_list = xalloc_observer_list_node (); observer_list->next = *list; observer_list->observer->notify = notify; observer_list->observer->data = data; *list = observer_list; return observer_list->observer; } static void generic_observer_detach (struct observer_list **list, const struct observer *observer) { struct observer_list *previous_node = NULL; struct observer_list *current_node = *list; while (current_node != NULL) { if (current_node->observer == observer) { if (previous_node != NULL) previous_node->next = current_node->next; else *list = current_node->next; xfree_observer_list_node (current_node); return; } previous_node = current_node; current_node = current_node->next; } /* We should never reach this point. However, this should not be a very serious error, so simply report a warning to the user. */ warning ("Failed to detach observer"); } static void generic_observer_notify (struct observer_list *list, const void *args) { struct observer_list *current_node = list; while (current_node != NULL) { (*current_node->observer->notify) (current_node->observer->data, args); current_node = current_node->next; } } /* normal_stop notifications. */ static struct observer_list *normal_stop_observers = NULL; void observer_normal_stop_notification_stub (const void *data, const void *unused_args) { observer_normal_stop_ftype *notify = (observer_normal_stop_ftype *) data; (*notify) (); } struct observer * observer_attach_normal_stop (observer_normal_stop_ftype *f) { return generic_observer_attach (&normal_stop_observers, &observer_normal_stop_notification_stub, (void *) f); } void observer_detach_normal_stop (struct observer *observer) { generic_observer_detach (&normal_stop_observers, observer); } void observer_notify_normal_stop (void) { generic_observer_notify (normal_stop_observers, NULL); }