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:
16:ff5d48fcce1b
Parent:
15:92d7c0b8a0f5
Child:
17:6d564266850e
--- a/EventQueue.cpp	Tue May 10 09:23:27 2016 -0500
+++ b/EventQueue.cpp	Mon Apr 18 09:47:21 2016 -0500
@@ -1,10 +1,7 @@
 #include "EventQueue.h"
 #include "Event.h"
 #include "mbed.h"
-
-#ifndef EVENTS_NO_RTOS
 #include "rtos.h"
-#endif
 
 
 // Platform specific definitions
@@ -18,14 +15,6 @@
     __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) {
@@ -56,39 +45,28 @@
     return _tick + (unsigned)_timer.read_ms();
 }
 
+bool EventQueue::past_tick(unsigned tick) {
+    return static_cast<int>(tick - get_tick()) <= 0;
+}
+
 void EventQueue::tick() {
     _timer.reset();
     _tick += 1 << 16;
 }
 
-void EventQueue::wakeup() {
-
-}
-
-void EventQueue::exit(volatile bool *exit) {
-    *exit = true;
-}
-
 void EventQueue::dispatch(int ms) {
-    Timeout timeout;
-    volatile bool exit = false;
-    
-    if (ms >= 0) {
-        Event<void(volatile bool*)> e(this, this, &EventQueue::exit);
-        e.delay(ms);
-        e.trigger(&exit);
-    }
+    unsigned target = get_tick() + (unsigned)ms;
 
     while (true) {
         while (_queue) {
-            int diff = (int)(_queue->target - get_tick());
-            if (diff > 0) {
-                timeout.attach_us(this, &EventQueue::wakeup, diff * 1000);
+            if (!past_tick(_queue->target)) {
                 break;
             }
 
+            unsigned primask = irq_disable();
             struct event *volatile e = _queue;
             _queue = _queue->next;
+            irq_enable(primask);
 
             e->dispatch(reinterpret_cast<void *>(e + 1));
 
@@ -99,11 +77,14 @@
             }
         }
 
-        if (exit) {
-            break;
+        if (ms >= 0 && past_tick(target)) {
+            return;
         }
 
-        irq_wfi();
+        osStatus status = Thread::yield();
+        if (status != osOK) {
+            return;
+        }
     }
 }
 
@@ -126,16 +107,28 @@
         return 0;
     }
 
+    unsigned target = get_tick() + (unsigned)ms;
     struct event *e;
 
-    unsigned primask = irq_disable();
-    e = _free;
-    if (e) {
-        _free = e->next;
+    while (true) {
+        if (_free) {
+            unsigned primask = irq_disable();
+            if (_free) {
+                e = _free;
+                _free = _free->next;
+            }
+            irq_enable(primask);
+        }
+
+        if (e || (ms >= 0 && past_tick(target))) {
+            return e;
+        }
+
+        osStatus status = Thread::yield();
+        if (status != osOK) {
+            return e;
+        }
     }
-    irq_enable(primask);
-
-    return e;
 }
 
 void EventQueue::dealloc(struct event *e) {