Poor man's subject/observer pattern.
authorbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sat, 27 May 2006 18:18:48 +0000 (18:18 +0000)
committerbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sat, 27 May 2006 18:18:48 +0000 (18:18 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@638 38d2e660-2303-0410-9eaa-f027e97ec537

mware/observer.c [new file with mode: 0755]
mware/observer.h [new file with mode: 0755]

diff --git a/mware/observer.c b/mware/observer.c
new file mode 100755 (executable)
index 0000000..9765960
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \brief Simple notifier for the observer/subject pattern (implementation)
+ *
+ * \version $Id$
+ * \author Bernardo Innocenti <bernie@develer.com>
+ */
+
+#include "observer.h"
+#include <cfg/cpu.h>  // 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 (executable)
index 0000000..8ca67e4
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \brief Simple notifier for the subject/observer pattern (interface)
+ *
+ * \version $Id$
+ * \author Bernardo Innocenti <bernie@develer.com>
+ */
+#ifndef MWARE_OBSERVER_H
+#define MWARE_OBSERVER_H
+
+#include <mware/list.h>
+
+/**
+ *
+ * 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 */