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:
2:11cda6bead99
Parent:
1:2202c19570e5
Child:
5:9963a617f952
--- a/EventQueue.cpp	Wed Apr 20 12:40:18 2016 -0500
+++ b/EventQueue.cpp	Wed Apr 20 14:15:54 2016 -0500
@@ -1,40 +1,78 @@
-#include <EventQueue.h>
-#include "mbed.h"
+#include "EventQueue.h"
+#include "Event.h"
 
 
-static void wakeup() {}
+EventQueue::EventQueue() {
+    _tick = 0;
+    _timer.start();
+    _ticker.attach_us(this, &EventQueue::tick, (1 << 16) * 1000);
+}
+
+unsigned EventQueue::get_tick() {
+    return _tick + (unsigned)_timer.read_ms();
+}
+
+void EventQueue::tick() {
+    _timer.reset();
+    _tick += 1 << 16;
+}
+
+void EventQueue::wakeup() {
+
+}
 
 void EventQueue::dispatch(int ms) {
-    mbed::Timer timer;
     mbed::Timeout timeout;
-    timer.start();
-    timeout.attach_us(wakeup, ms * 1000);
+    struct event exit;
+    
+    if (ms >= 0) {
+        memset(&exit, 0, sizeof exit);
+        event_register(&exit, ms);
+    }
 
     while (true) {
         while (_queue) {
-            _queue->callback(_queue->data);
+            int diff = (int)(_queue->target - get_tick());
+            if (diff > 0) {
+                timeout.attach_us(this, &EventQueue::wakeup, diff * 1000);
+                break;
+            }
+
+            struct event *volatile e = _queue;
             _queue = _queue->next;
-        }
+            e->registered = false;
+
+            if (e == &exit) {
+                return;
+            }
 
-        if (ms >= 0 && timer.read_ms() >= ms) {
-            break;
+            e->callback(e->data);
+
+            if (e->period >= 0) {
+                event_register(e, e->period);
+            }
         }
 
         __WFI();
     }
 }
 
-void EventQueue::event_register(struct event *event) {
+void EventQueue::event_register(struct event *event, int ms) {
+    if (event->registered) {
+        return;
+    }
+
+    event->target = get_tick() + (unsigned)ms;
+    event->registered = true;
+
     __disable_irq();
-    for (struct event *volatile *p = &_queue;; p = &(*p)->next) {
-        if (!*p) {
-            event->next = 0;
-            *p = event;
-            break;
-        } else if (*p == event) {
-            break;
-        }
+    struct event *volatile *p = &_queue;
+    while (*p && (*p)->target < event->target) {
+        p = &(*p)->next;
     }
+
+    event->next = *p;
+    *p = event;
     __enable_irq();
 }