From c0497acd00178a56ebeeb7b7045b35db1ba0288f Mon Sep 17 00:00:00 2001 From: bernie Date: Sat, 27 May 2006 18:18:48 +0000 Subject: [PATCH] Poor man's subject/observer pattern. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@638 38d2e660-2303-0410-9eaa-f027e97ec537 --- mware/observer.c | 56 ++++++++++++++++++++++++++++++++++++++ mware/observer.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100755 mware/observer.c create mode 100755 mware/observer.h diff --git a/mware/observer.c b/mware/observer.c new file mode 100755 index 00000000..97659600 --- /dev/null +++ b/mware/observer.c @@ -0,0 +1,56 @@ +/** + * \file + * + * + * \brief Simple notifier for the observer/subject pattern (implementation) + * + * \version $Id$ + * \author Bernardo Innocenti + */ + +#include "observer.h" +#include // IRQ_DISABLE/IRQ_ENABLE + + +void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)) +{ + observer->event = event; +} + +void observer_InitSubject(Subject *subject) +{ + LIST_INIT(&subject->observers); +} + +void observer_Subscribe(Subject *subject, Observer *observer) +{ + ATOMIC(ADDHEAD(&subject->observers, &observer->link)); +} + +void observer_Unsubscribe(UNUSED_ARG(Subject *,subject), Observer *observer) +{ + ATOMIC(REMOVE(&observer->link)); +} + +void observer_notify(Subject *subject, int event_id, void *param) +{ + Observer *observer; + cpuflags_t irqstate; + IRQ_SAVE_DISABLE(irqstate); + + /* + * Run over list with protection against other + * threads, but re-enable irqs in callbacks. + */ + FOREACH_NODE(observer, &subject->observers) + { + IRQ_RESTORE(irqstate); + observer->event(event_id, param); + IRQ_SAVE_DISABLE(irqstate); + } + + IRQ_RESTORE(irqstate); +} diff --git a/mware/observer.h b/mware/observer.h new file mode 100755 index 00000000..8ca67e48 --- /dev/null +++ b/mware/observer.h @@ -0,0 +1,71 @@ +/** + * \file + * + * + * \brief Simple notifier for the subject/observer pattern (interface) + * + * \version $Id$ + * \author Bernardo Innocenti + */ +#ifndef MWARE_OBSERVER_H +#define MWARE_OBSERVER_H + +#include + +/** + * + * Here's a simple example: + * + * \code + * Subject kbd_driver; + * + * Observer kbd_observer; + * + * void key_pressed(int event, void *_param) + * { + * char *param = (char *)_param; + * + * if (event == EVENT_KBD_PRESSED) + * printf("You pressed %c\n", *param); + * } + * + * void register_kbd_listener(void) + * { + * observer_SetEvent(&kbd_observer, key_pressed); + * observer_Subscribe(&kbd_driver, &kbd_observer); + * } + * \endcode + */ +typedef struct Observer +{ + Node link; + void (*event)(int event_id, void *param); +} Observer; + +typedef struct Subject +{ + /// Subscribed observers. + List observers; + +} Subject; + +void observer_SetEvent(Observer *observer, void (*event)(int event_id, void *param)); + +#define OBSERVER_INITIALIZER(callback) { { NULL, NULL }, callback } + +void observer_InitSubject(Subject *subject); + +/// Aggiunge un Observer all'insieme +void observer_Subscribe(Subject *subject, Observer *observer); + +/// Rimuove un Observer dall'insieme +void observer_Unsubscribe(Subject *subject, Observer *observer); + +/// per tutti gli elementi nel set notifica l'evento, chiamando la relativa +/// funzione event +void observer_notify(Subject *subject, int event_id, void *param); + +#endif /* MWARE_OBSERVER_H */ -- 2.25.1