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.

EventQueue.h

Committer:
Christopher Haster
Date:
2016-04-18
Revision:
16:ff5d48fcce1b
Parent:
15:92d7c0b8a0f5
Child:
17:6d564266850e

File content as of revision 16:ff5d48fcce1b:

/*  EventQueue
 *
 *  Flexible queue for managing events
 */
#ifndef EVENT_QUEUE_H
#define EVENT_QUEUE_H

#include "Timer.h"
#include "Ticker.h"
#include "FuncPtr.h"
#include "Binder.h"


/** Flexible queue for managing events
 */
class EventQueue {
public:
    /** Create an event queue
     *  @param event_count      Number of events to allow enqueueing at once
     *  @param event_context    Max size of arguments passed with an event
     */
    EventQueue(unsigned event_count=32,
               unsigned event_context=0);

    /** Clean up event queue
     */
    ~EventQueue();

    /** Dispatch pending events
     *  @param ms       Time to wait for events in milliseconds,
     *                  0 indicates to return immediately if no events are pending
     */
    void dispatch(int ms=-1);

    /** Get current tick of the event queue
     *  @return         Number of milliseconds since the queue was instantiated,
     *                  this count intentionally overflows to 0 after 2^32-1
     */
    unsigned get_tick();

    /** Determine if tick has been passed
     *  @param          Tick to check
     *  @param          True if tick has been passed
     */
    bool past_tick(unsigned tick);

private:
    struct event {
        struct event *volatile next;
        unsigned target;
        int period;

        void (*dispatch)(void *p);
        // data follows
    };

    struct event *alloc(unsigned size, int ms=-1);
    void dealloc(struct event *);

    void trigger(struct event *e, int delay);

    template <typename F>
    bool trigger(F func, int delay, int period, int tolerance, int ms=-1) {
        struct event *e = alloc(sizeof(F), ms);
        if (!e) {
            return false;
        }

        e->period = period;
        (void)tolerance; // unused
        e->dispatch = &F::thunk;
        *reinterpret_cast<F*>(e+1) = func;

        trigger(e, delay);
        return true;
    }

    void tick();

    unsigned _event_context;
    void *_mem;
    struct event *volatile _free;
    struct event *volatile _queue;

    unsigned _tick;
    mbed::Ticker _ticker;
    mbed::Timer _timer;

    template <typename F>
    friend class Event;
};


#endif