Note! This project has moved to github.com/armmbed/mbed-events

Dependents:   SimpleHTTPExample

This repository has been superceded

This project has moved to mbed-events

Composable event loops combine the cheap synchronicity of event loops with the composability of preempted threads.

Two modular event queue classes are provided:

  • EventLoop - for loops coupled with a c++ managed thread
  • EventQueue - for manually managed event queues

The Event class takes advantage of the extensibility of FuncPtr to allow an event to be passed through APIs as a normal function.

More information on composable event loops.

Revision:
15:92d7c0b8a0f5
Parent:
14:5abf2ccf2dbf
Child:
16:ff5d48fcce1b
--- a/EventQueue.cpp	Tue May 10 07:51:44 2016 -0500
+++ b/EventQueue.cpp	Tue May 10 09:23:27 2016 -0500
@@ -7,7 +7,27 @@
 #endif
 
 
+// Platform specific definitions
+static inline unsigned irq_disable() {
+    unsigned primask = __get_PRIMASK();
+    __disable_irq();
+    return primask;
+}
 
+static inline void irq_enable(unsigned primask) {
+    __set_PRIMASK(primask);
+}
+
+static inline void irq_wfi() {
+#ifndef EVENTS_NO_RTOS
+    Thread::yield();
+#else
+    __WFI();
+#endif
+}
+
+
+// Event queue definitions
 EventQueue::EventQueue(unsigned event_count, unsigned event_context) {
     _event_context = sizeof(FuncPtr<void()>) + event_context;
     unsigned event_size = sizeof(struct event) + _event_context;
@@ -45,12 +65,18 @@
 
 }
 
+void EventQueue::exit(volatile bool *exit) {
+    *exit = true;
+}
+
 void EventQueue::dispatch(int ms) {
     Timeout timeout;
-    struct event exit;
+    volatile bool exit = false;
     
     if (ms >= 0) {
-        trigger(&exit, ms);
+        Event<void(volatile bool*)> e(this, this, &EventQueue::exit);
+        e.delay(ms);
+        e.trigger(&exit);
     }
 
     while (true) {
@@ -64,10 +90,6 @@
             struct event *volatile e = _queue;
             _queue = _queue->next;
 
-            if (e == &exit) {
-                return;
-            }
-
             e->dispatch(reinterpret_cast<void *>(e + 1));
 
             if (e->period >= 0) {
@@ -77,20 +99,18 @@
             }
         }
 
-#ifndef EVENTS_NO_RTOS
-        Thread::yield();
-#else
-        __WFI();
-#endif
+        if (exit) {
+            break;
+        }
+
+        irq_wfi();
     }
 }
 
 void EventQueue::trigger(struct event *e, int delay) {
     e->target = get_tick() + (unsigned)delay;
 
-    uint32_t primask = __get_PRIMASK();
-    __disable_irq();
-
+    unsigned primask = irq_disable();
     struct event *volatile *p = &_queue;
     while (*p && (*p)->target < e->target) {
         p = &(*p)->next;
@@ -98,8 +118,7 @@
 
     e->next = *p;
     *p = e;
-
-    __set_PRIMASK(primask);
+    irq_enable(primask);
 }
 
 EventQueue::event *EventQueue::alloc(unsigned size, int ms) {
@@ -109,27 +128,20 @@
 
     struct event *e;
 
-    uint32_t primask = __get_PRIMASK();
-    __disable_irq();
-
+    unsigned primask = irq_disable();
     e = _free;
     if (e) {
         _free = e->next;
     }
-
-    __set_PRIMASK(primask);
+    irq_enable(primask);
 
     return e;
 }
 
 void EventQueue::dealloc(struct event *e) {
-    uint32_t primask = __get_PRIMASK();
-    __disable_irq();
-
+    unsigned primask = irq_disable();
     e->next = _free;
     _free = e;
-
-    __set_PRIMASK(primask);
-
+    irq_enable(primask);
 }