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.

Event.h

Committer:
Christopher Haster
Date:
2016-04-18
Revision:
20:2f9d9c53a5af
Parent:
17:6d564266850e

File content as of revision 20:2f9d9c53a5af:

/*  Event
 *
 *  Pendable event
 */
#ifndef EVENT_H
#define EVENT_H

#include "EventQueue.h"
#include "FuncPtr.h"
#include "Binder.h"


/** Pendable event class
 */
template <typename F>
class Event;

/** Pendable event class
 */
template <typename A0, typename A1, typename A2, typename A3, typename A4>
class Event<void(A0, A1, A2, A3, A4)> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3, A4)> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void(A0, A1, A2, A3, A4)> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void(A0, A1, A2, A3, A4)>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3, A4)> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, int ms=-1) {
        return _queue->event_trigger(
                Binder<void(A0,A1,A2,A3,A4),A0,A1,A2,A3,A4>(_func,a0,a1,a2,a3,a4),
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
        trigger(a0, a1, a2, a3, a4);
    }

    /** Post the event onto the bound queue
     */
    void operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
        return call(a0, a1, a2, a3, a4);
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
        return static_cast<Event<void(A0, A1, A2, A3, A4)>*>(data)
                ->call(a0, a1, a2, a3, a4);
    }

private:
    FuncPtr<void(A0,A1,A2,A3,A4)> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};

/** Pendable event class
 */
template <typename A0, typename A1, typename A2, typename A3>
class Event<void(A0, A1, A2, A3)> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2, A3)> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void(A0, A1, A2, A3)> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void(A0, A1, A2, A3)>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2, A3)> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(A0 a0, A1 a1, A2 a2, A3 a3, int ms=-1) {
        return _queue->event_trigger(
                Binder<void(A0,A1,A2,A3),A0,A1,A2,A3>(_func,a0,a1,a2,a3),
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call(A0 a0, A1 a1, A2 a2, A3 a3) {
        trigger(a0, a1, a2, a3);
    }

    /** Post the event onto the bound queue
     */
    void operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
        return call(a0, a1, a2, a3);
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data, A0 a0, A1 a1, A2 a2, A3 a3) {
        return static_cast<Event<void(A0, A1, A2, A3)>*>(data)
                ->call(a0, a1, a2, a3);
    }

private:
    FuncPtr<void(A0,A1,A2,A3)> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};

/** Pendable event class
 */
template <typename A0, typename A1, typename A2>
class Event<void(A0, A1, A2)> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void(A0, A1, A2)> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void(A0, A1, A2)> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void(A0, A1, A2)>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void(A0, A1, A2)> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(A0 a0, A1 a1, A2 a2, int ms=-1) {
        return _queue->event_trigger(
                Binder<void(A0,A1,A2),A0,A1,A2>(_func,a0,a1,a2),
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call(A0 a0, A1 a1, A2 a2) {
        trigger(a0, a1, a2);
    }

    /** Post the event onto the bound queue
     */
    void operator()(A0 a0, A1 a1, A2 a2) {
        return call(a0, a1, a2);
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data, A0 a0, A1 a1, A2 a2) {
        return static_cast<Event<void(A0, A1, A2)>*>(data)
                ->call(a0, a1, a2);
    }

private:
    FuncPtr<void(A0,A1,A2)> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};

/** Pendable event class
 */
template <typename A0, typename A1>
class Event<void(A0, A1)> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void(A0, A1)> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void(A0, A1)> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void(A0, A1)>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void(A0, A1)> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(A0 a0, A1 a1, int ms=-1) {
        return _queue->event_trigger(
                Binder<void(A0,A1),A0,A1>(_func,a0,a1),
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call(A0 a0, A1 a1) {
        trigger(a0, a1);
    }

    /** Post the event onto the bound queue
     */
    void operator()(A0 a0, A1 a1) {
        return call(a0, a1);
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data, A0 a0, A1 a1) {
        return static_cast<Event<void(A0, A1)>*>(data)
                ->call(a0, a1);
    }

private:
    FuncPtr<void(A0,A1)> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};

/** Pendable event class
 */
template <typename A0>
class Event<void(A0)> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void(A0)> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void(A0)> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void(A0)>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void(A0)> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(A0 a0, int ms=-1) {
        return _queue->event_trigger(
                Binder<void(A0),A0>(_func,a0),
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call(A0 a0) {
        trigger(a0);
    }

    /** Post the event onto the bound queue
     */
    void operator()(A0 a0) {
        return call(a0);
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data, A0 a0) {
        return static_cast<Event<void(A0)>*>(data)
                ->call(a0);
    }

private:
    FuncPtr<void(A0)> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};

/** Pendable event class
 */
template <>
class Event<void()> {
public:
    /** Create an event bound to a queue
     */
    Event(EventQueue *queue=0, FuncPtr<void()> func=0) {
        _delay = 0;
        _period = -1;
        attach(queue, func);
    }

    /** Create an event bound to a queue
     */
    template <typename T, typename M>
    Event(EventQueue *queue, T *obj, M method) {
        _delay = 0;
        _period = -1;
        attach(queue, obj, method);
    }

    /** Attach an event to a queue
     */
    void attach(EventQueue *queue) {
        _queue = queue;
    }

    /** Attach a callback to an event
     */
    void attach(FuncPtr<void()> func) {
        _func.attach(func);
    }

    /** Attach a callback to an event
     */
    template <typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void()>(obj, method));
    }

    /** Attach a func to an event
     */
    void attach(EventQueue *queue, FuncPtr<void()> func) {
        attach(queue);
        attach(func);
    }

    /** Attach an event to a queue
     */
    template <typename T, typename M>
    void attach(EventQueue *queue, T *obj, M method) {
        attach(queue);
        attach(obj, method);
    }

    /** Set delay for when the event is dispatched after it is posted
     *  @param ms   Delay in milliseconds
     */
    void delay(int ms) {
        _delay = ms;
    }

    /** Set event to repeat periodically after it is posted
     *  @param ms   Period in milliseconds
     */
    void period(int ms) {
        _period = ms;
    }

    /** Set tolerance hint on when the event must be called, defaults to 0
     *  @param ms   Tolerance in milliseconds
     */
    void tolerance(int ms) {
        _tolerance = ms;
    }

    /** Post the event onto the bound queue
     *  @param ms   Max time to wait if memory is not available in milliseconds
     *  @return     True if the event was posted successfully
     */
    bool trigger(int ms=-1) {
        return _queue->event_trigger(_func,
                _delay, _period, _tolerance, ms);
    }

    /** Post the event onto the bound queue
     */
    void call() {
        trigger();
    }

    /** Post the event onto the bound queue
     */
    void operator()() {
        return call();
    }

    /** Test if event has been bound
     */
    operator bool() const {
        return _func && _queue;
    }

    /** Static thunk for passing as C-style function
     *  @param data Event to dispatch passed as void pointer
     */
    static void thunk(void *data) {
        return static_cast<Event<void()>*>(data)
                ->call();
    }

private:
    FuncPtr<void()> _func;
    EventQueue *_queue;
    int _delay;
    int _period;
    int _tolerance;
};


#endif