@@ -45,6 +45,8 @@ namespace events {
4545// Predeclared classes
4646template <typename F>
4747class Event ;
48+ template <typename F, typename A>
49+ class UserAllocatedEvent ;
4850
4951/* *
5052 * \defgroup events_EventQueue EventQueue class
@@ -60,10 +62,17 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
6062 /* * Create an EventQueue
6163 *
6264 * Create an event queue. The event queue either allocates a buffer of
63- * the specified size with malloc or uses the user provided buffer.
65+ * the specified size with malloc or uses the user provided buffer or
66+ * uses 1B dummy buffer if 0 size passed.
67+ *
68+ * 0 size queue is a special purpose queue to dispatch static events
69+ * only (see UserAllocatedEvent). Such a queue gives the guarantee
70+ * that no dynamic memory allocation will take place while queue
71+ * creation and events posting & dispatching.
6472 *
6573 * @param size Size of buffer to use for events in bytes
6674 * (default to EVENTS_QUEUE_SIZE)
75+ * If 0 provided then 1B dummy buffer is used
6776 * @param buffer Pointer to buffer to use for events
6877 * (default to NULL)
6978 */
@@ -139,6 +148,34 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
139148 */
140149 bool cancel (int id);
141150
151+ /* * Cancel an in-flight user allocated event
152+ *
153+ * Attempts to cancel an UserAllocatedEvent referenced by its address
154+ * It is safe to call cancel after an event has already been dispatched.
155+ *
156+ * Event must be valid i.e. event must have not finished executing
157+ * and must have been bound to this queue.
158+ *
159+ * The cancel function is IRQ safe.
160+ *
161+ * If called while the event queue's dispatch loop is active in another thread,
162+ * the cancel function does not guarantee that the event will not execute after it
163+ * returns, as the event may have already begun executing. A call made from
164+ * the same thread as the dispatch loop will always succeed with a valid id.
165+ *
166+ * @param event Address of the event
167+ * @return true if event was successfully cancelled
168+ * false if event was not cancelled (invalid queue or executing already begun)
169+ */
170+ template <typename ... Args>
171+ bool cancel (UserAllocatedEvent<Args...> *event)
172+ {
173+ if (event->_equeue != &_equeue) {
174+ return false ;
175+ }
176+ return equeue_cancel_user_allocated (&_equeue, event);
177+ }
178+
142179 /* * Query how much time is left for delayed event
143180 *
144181 * If the event is delayed, this function can be used to query how much time
@@ -158,6 +195,33 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
158195 */
159196 int time_left (int id);
160197
198+ /* * Query how much time is left for delayed UserAllocatedEvent
199+ *
200+ * If the event is delayed, this function can be used to query how much time
201+ * is left until the event is due to be dispatched.
202+ *
203+ * Event must be valid i.e. event must have not finished executing
204+ * and must have been bound to this queue.
205+ *
206+ * This function is IRQ safe.
207+ *
208+ * @param event Address of the event
209+ *
210+ * @return Remaining time in milliseconds or
211+ * 0 if event is already due to be dispatched or
212+ * is currently executing.
213+ * Undefined if id is invalid.
214+ *
215+ */
216+ template <typename ... Args>
217+ int time_left (UserAllocatedEvent<Args...> *event)
218+ {
219+ if (event && event->_equeue != &_equeue) {
220+ return -1 ;
221+ }
222+ return equeue_timeleft_user_allocated (&_equeue, &event->_e );
223+ }
224+
161225 /* * Background an event queue onto a single-shot timer-interrupt
162226 *
163227 * When updated, the event queue will call the provided update function
@@ -597,6 +661,53 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
597661 template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
598662 Event<void (Args...)> event (mbed::Callback<R(BoundArgs..., Args...)> cb, ContextArgs ...context_args);
599663
664+ /* * Creates an user allocated event bound to the event queue
665+ *
666+ * Constructs an user allocated event bound to the specified event queue.
667+ * The specified callback acts as the target for the event and is executed
668+ * in the context of the event queue's dispatch loop once posted.
669+ *
670+ * @code
671+ * #include "mbed.h"
672+ *
673+ * void handler(int data) { ... }
674+ *
675+ * class Device {
676+ * public:
677+ * void handler(int data) { ... }
678+ * };
679+ *
680+ * Device dev;
681+ *
682+ * // queue with not internal storage for dynamic events
683+ * // accepts only user allocated events
684+ * static EventQueue queue(0);
685+ * // Create events
686+ * static auto e1 = make_user_allocated_event(&dev, Device::handler, 2);
687+ * static auto e2 = queue.make_user_allocated_event(handler, 3);
688+ *
689+ * int main()
690+ * {
691+ * e1.call_on(&queue);
692+ * e2.call();
693+ *
694+ * queue.dispatch(1);
695+ * }
696+ * @endcode
697+ *
698+ * @param f Function to execute when the event is dispatched
699+ * @return Event that will dispatch on the specific queue
700+ */
701+ template <typename F, typename ... ArgTs>
702+ UserAllocatedEvent<F, void (ArgTs...)> make_user_allocated_event (F f, ArgTs... args);
703+
704+ /* * Creates an user allocated event bound to the event queue
705+ * @see EventQueue::make_user_allocated_event
706+ */
707+ template <typename T, typename R, typename ... ArgTs>
708+ UserAllocatedEvent<mbed::Callback<void (ArgTs...)>, void (ArgTs...)> make_user_allocated_event (T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
709+
710+
600711#else
601712
602713 /* * Calls an event on the queue
@@ -1068,12 +1179,50 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
10681179 */
10691180 template <typename R, typename B0, typename B1, typename B2, typename B3, typename B4, typename C0, typename C1, typename C2, typename C3, typename C4, typename ... ArgTs>
10701181 Event<void (ArgTs...)> event (mbed::Callback<R(B0, B1, B2, B3, B4, ArgTs...)> cb, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1182+
1183+ /* * Creates an user allocated event bound to the event queue
1184+ *
1185+ * Constructs an user allocated event bound to the specified event queue.
1186+ * The specified callback acts as the target for the event and is executed
1187+ * in the context of the event queue's dispatch loop once posted.
1188+ *
1189+ * @param f Function to execute when the event is dispatched
1190+ * @return Event that will dispatch on the specific queue
1191+ */
1192+ template <typename F, typename ... ArgTs>
1193+ UserAllocatedEvent<F, void (ArgTs...)> make_user_allocated_event (F f, ArgTs... args);
1194+
1195+ /* * Creates an user allocated event bound to the event queue
1196+ * @see EventQueue::make_user_allocated_event
1197+ */
1198+ template <typename T, typename R, typename ... ArgTs>
1199+ UserAllocatedEvent<mbed::Callback<void (ArgTs...)>, void (ArgTs...)> make_user_allocated_event (T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
1200+
1201+ /* * Creates an user allocated event bound to the event queue
1202+ * @see EventQueue::make_user_allocated_event
1203+ */
1204+ template <typename T, typename R, typename ... ArgTs>
1205+ UserAllocatedEvent<mbed::Callback<void (ArgTs...)>, void (ArgTs...)> make_user_allocated_event (const T *obj, R(T::*method)(ArgTs... args) const , ArgTs... args);
1206+
1207+ /* * Creates an user allocated event bound to the event queue
1208+ * @see EventQueue::make_user_allocated_event
1209+ */
1210+ template <typename T, typename R, typename ... ArgTs>
1211+ UserAllocatedEvent<mbed::Callback<void (ArgTs...)>, void (ArgTs...)> make_user_allocated_event (volatile T *obj, R(T::*method)(ArgTs... args) volatile, ArgTs... args);
1212+
1213+ /* * Creates an user allocated event bound to the event queue
1214+ * @see EventQueue::make_user_allocated_event
1215+ */
1216+ template <typename T, typename R, typename ... ArgTs>
1217+ UserAllocatedEvent<mbed::Callback<void (ArgTs...)>, void (ArgTs...)> make_user_allocated_event (const volatile T *obj, R(T::*method)(ArgTs... args) const volatile, ArgTs... args);
10711218#endif
10721219
10731220protected:
10741221#if !defined(DOXYGEN_ONLY)
10751222 template <typename F>
10761223 friend class Event ;
1224+ template <typename F, typename A>
1225+ friend class UserAllocatedEvent ;
10771226 struct equeue _equeue;
10781227 mbed::Callback<void (int )> _update;
10791228
@@ -1098,7 +1247,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
10981247 struct context <F> {
10991248 F f;
11001249
1101- context (F f)
1250+ constexpr context (F f)
11021251 : f(f) {}
11031252
11041253 template <typename ... ArgTs>
@@ -1113,7 +1262,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
11131262 F f;
11141263 C0 c0;
11151264
1116- context (F f, C0 c0)
1265+ constexpr context (F f, C0 c0)
11171266 : f(f), c0(c0) {}
11181267
11191268 template <typename ... ArgTs>
@@ -1129,7 +1278,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
11291278 C0 c0;
11301279 C1 c1;
11311280
1132- context (F f, C0 c0, C1 c1)
1281+ constexpr context (F f, C0 c0, C1 c1)
11331282 : f(f), c0(c0), c1(c1) {}
11341283
11351284 template <typename ... ArgTs>
@@ -1146,7 +1295,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
11461295 C1 c1;
11471296 C2 c2;
11481297
1149- context (F f, C0 c0, C1 c1, C2 c2)
1298+ constexpr context (F f, C0 c0, C1 c1, C2 c2)
11501299 : f(f), c0(c0), c1(c1), c2(c2) {}
11511300
11521301 template <typename ... ArgTs>
@@ -1164,7 +1313,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
11641313 C2 c2;
11651314 C3 c3;
11661315
1167- context (F f, C0 c0, C1 c1, C2 c2, C3 c3)
1316+ constexpr context (F f, C0 c0, C1 c1, C2 c2, C3 c3)
11681317 : f(f), c0(c0), c1(c1), c2(c2), c3(c3) {}
11691318
11701319 template <typename ... ArgTs>
@@ -1183,7 +1332,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
11831332 C3 c3;
11841333 C4 c4;
11851334
1186- context (F f, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4)
1335+ constexpr context (F f, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4)
11871336 : f(f), c0(c0), c1(c1), c2(c2), c3(c3), c4(c4) {}
11881337
11891338 template <typename ... ArgTs>
0 commit comments