Mistake on this page?
Report an issue in GitHub or email us
EventQueue.h
1 /*
2  * Copyright (c) 2016-2019 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef EVENT_QUEUE_H
19 #define EVENT_QUEUE_H
20 
21 #include "events/equeue.h"
22 #include "platform/Callback.h"
23 #include "platform/NonCopyable.h"
24 #include <cstddef>
25 #include <utility>
26 #include <chrono>
27 #include <new>
28 
29 namespace events {
30 /**
31  * \addtogroup events-public-api
32  * @{
33  */
34 
35 /** EVENTS_EVENT_SIZE
36  * Minimum size of an event
37  * This size fits a Callback<void()> at minimum
38  */
39 #define EVENTS_EVENT_SIZE \
40  (EQUEUE_EVENT_SIZE - 2*sizeof(void*) + sizeof(mbed::Callback<void()>))
41 
42 /** EVENTS_QUEUE_SIZE
43  * Default size of buffer for events
44  */
45 #define EVENTS_QUEUE_SIZE (32*EVENTS_EVENT_SIZE)
46 
47 // Predeclared classes
48 template <typename F>
49 class Event;
50 template <typename F, typename A>
52 
53 /**
54  * \defgroup events_EventQueue EventQueue class
55  * @{
56  */
57 
58 /** EventQueue
59  *
60  * Flexible event queue for dispatching events
61  */
62 class EventQueue : private mbed::NonCopyable<EventQueue> {
63 public:
64  using duration = std::chrono::duration<int, std::milli>;
65 
66  /** Create an EventQueue
67  *
68  * Create an event queue. The event queue either allocates a buffer of
69  * the specified size with malloc or uses the user provided buffer or
70  * uses 1B dummy buffer if 0 size passed.
71  *
72  * 0 size queue is a special purpose queue to dispatch static events
73  * only (see UserAllocatedEvent). Such a queue gives the guarantee
74  * that no dynamic memory allocation will take place while queue
75  * creation and events posting & dispatching.
76  *
77  * @param size Size of buffer to use for events in bytes
78  * (default to EVENTS_QUEUE_SIZE)
79  * If 0 provided then 1B dummy buffer is used
80  * @param buffer Pointer to buffer to use for events
81  * (default to NULL)
82  */
83  EventQueue(unsigned size = EVENTS_QUEUE_SIZE, unsigned char *buffer = NULL);
84 
85  /** Destroy an EventQueue
86  */
87  ~EventQueue();
88 
89  /** Dispatch events
90  *
91  * Executes events for the specified number of milliseconds.
92  *
93  * The dispatch_for() function is guaranteed to terminate after the elapsed wait.
94  *
95  * @param ms Time to wait for events in milliseconds, expressed as a
96  * Chrono duration.
97  */
98  void dispatch_for(duration ms);
99 
100  /** Dispatch events
101  *
102  * Executes events until the specified milliseconds have passed.
103  * If ms is negative, the dispatch function will dispatch events
104  * indefinitely or until break_dispatch is called on this queue.
105  *
106  * When called with a finite timeout, the dispatch function is guaranteed
107  * to terminate. When called with a timeout of 0, the dispatch function
108  * does not wait and is IRQ safe.
109  *
110  * NOTE: Since the majority of the event library was updated to use
111  * Chrono types (as part of the Mbed 6 release), this function will not
112  * function as expected. Please update to use the new dispatch functions
113  * to ensure correct functionality.
114  *
115  * @param ms Time to wait for events in milliseconds, a negative
116  * value will dispatch events indefinitely
117  * (default to -1)
118  */
119  MBED_DEPRECATED_SINCE("mbed-os-6.7.0", "Use dispatch_for() to pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
120  void dispatch(int ms = -1);
121 
122  /** Dispatch events without a timeout
123  *
124  * Executes events indefinitely unless the dispatch loop is forcibly broken.
125  * @See break_dispatch()
126  *
127  */
128  void dispatch_forever();
129 
130  /** Dispatch currently queued events only and then terminate
131  *
132  * In this case the dispatch function does not wait.
133  *
134  */
135  void dispatch_once();
136 
137  /** Break out of a running event loop
138  *
139  * Forces the specified event queue's dispatch loop to terminate. Pending
140  * events may finish executing, but no new events will be executed.
141  */
142  void break_dispatch();
143 
144  /** Millisecond counter
145  *
146  * Returns the underlying tick of the event queue represented as the
147  * number of milliseconds that have passed since an arbitrary point in
148  * time. Intentionally overflows to 0 after 2^32-1.
149  *
150  * @return The underlying tick of the event queue in milliseconds
151  */
152  unsigned tick();
153 
154  /** Cancel an in-flight event
155  *
156  * Attempts to cancel an event referenced by the unique id returned from
157  * one of the call functions. It is safe to call cancel after an event
158  * has already been dispatched.
159  *
160  * id must be valid i.e. event must have not finished executing.
161  *
162  * The cancel function is IRQ safe.
163  *
164  * If called while the event queue's dispatch loop is active in another thread,
165  * the cancel function does not guarantee that the event will not execute after it
166  * returns, as the event may have already begun executing. A call made from
167  * the same thread as the dispatch loop will always succeed with a valid id.
168  *
169  * @param id Unique id of the event
170  * @return true if event was successfully cancelled
171  * false if event was not cancelled (invalid id or executing already begun)
172  */
173  bool cancel(int id);
174 
175  /** Cancel an in-flight user allocated event
176  *
177  * Attempts to cancel an UserAllocatedEvent referenced by its address
178  * It is safe to call cancel after an event has already been dispatched.
179  *
180  * Event must be valid i.e. event must have not finished executing
181  * and must have been bound to this queue.
182  *
183  * The cancel function is IRQ safe.
184  *
185  * If called while the event queue's dispatch loop is active in another thread,
186  * the cancel function does not guarantee that the event will not execute after it
187  * returns, as the event may have already begun executing. A call made from
188  * the same thread as the dispatch loop will always succeed with a valid id.
189  *
190  * @param event Address of the event
191  * @return true if event was successfully cancelled
192  * false if event was not cancelled (invalid queue or executing already begun)
193  */
194  template<typename F, typename A>
196  {
197  if (event->_equeue != &_equeue) {
198  return false;
199  }
200  return equeue_cancel_user_allocated(&_equeue, event);
201  }
202 
203  /** Query how much time is left for delayed event
204  *
205  * If the event is delayed, this function can be used to query how much time
206  * is left until the event is due to be dispatched.
207  *
208  * id must be valid i.e. event must have not finished executing.
209  *
210  * This function is IRQ safe.
211  *
212  * @param id Unique id of the event
213  *
214  * @return Remaining time in milliseconds or
215  * 0 if event is already due to be dispatched or
216  * is currently executing.
217  * Undefined if id is invalid.
218  *
219  */
220  int time_left(int id);
221 
222  /** Query how much time is left for delayed UserAllocatedEvent
223  *
224  * If the event is delayed, this function can be used to query how much time
225  * is left until the event is due to be dispatched.
226  *
227  * Event must be valid i.e. event must have not finished executing
228  * and must have been bound to this queue.
229  *
230  * This function is IRQ safe.
231  *
232  * @param event Address of the event
233  *
234  * @return Remaining time in milliseconds or
235  * 0 if event is already due to be dispatched or
236  * is currently executing.
237  * Undefined if id is invalid.
238  *
239  */
240  template<typename F, typename A>
242  {
243  if (event && event->_equeue != &_equeue) {
244  return -1;
245  }
246  return equeue_timeleft_user_allocated(&_equeue, &event->_e);
247  }
248 
249  /** Background an event queue onto a single-shot timer-interrupt
250  *
251  * When updated, the event queue will call the provided update function
252  * with a timeout indicating when the queue should be dispatched. A
253  * negative timeout will be passed to the update function when the
254  * timer-interrupt is no longer needed.
255  *
256  * Passing a null function disables the existing update function.
257  *
258  * The background function allows an event queue to take advantage of
259  * hardware timers or other event loops, allowing an event queue to be
260  * ran in the background without consuming the foreground thread.
261  *
262  * @param update Function called to indicate when the queue should be
263  * dispatched
264  */
265  void background(mbed::Callback<void(int)> update);
266 
267  /** Chain an event queue onto another event queue
268  *
269  * After chaining a queue to a target, calling dispatch on the target
270  * queue will also dispatch events from this queue. The queues use
271  * their own buffers and events must be handled independently.
272  *
273  * A null queue as the target will unchain the existing queue.
274  *
275  * The chain function allows multiple event queues to be composed,
276  * sharing the context of a dispatch loop while still being managed
277  * independently
278  *
279  * @param target Queue that will dispatch this queue's events as a
280  * part of its dispatch loop
281  *
282  * @return Zero on success and negative error code value if chaining fails
283  *
284  */
285  int chain(EventQueue *target);
286 
287 
288 
289 #if defined(DOXYGEN_ONLY)
290  /** Calls an event on the queue
291  *
292  * The specified callback will be executed in the context of the event
293  * queue's dispatch loop.
294  *
295  * The call function is IRQ safe and can act as a mechanism for moving
296  * events out of IRQ contexts.
297  *
298  * @param f Function to execute in the context of the dispatch loop
299  * @param args Arguments to pass to the callback
300  * @return A unique id that represents the posted event and can
301  * be passed to cancel, or an id of 0 if there is not
302  * enough memory to allocate the event.
303  * Returned id will remain valid until event has finished
304  * executing.
305  *
306  * @code
307  * #include "mbed.h"
308  *
309  * int main() {
310  * // creates a queue with the default size
311  * EventQueue queue;
312  *
313  * // events are simple callbacks
314  * queue.call(printf, "called immediately\n");
315  *
316  * // the dispatch method executes events
317  * queue.dispatch();
318  * }
319  * @endcode
320  */
321  template <typename F, typename ...Args>
322  int call(F f, Args ...args);
323 
324  /** Calls an event on the queue
325  *
326  * The specified callback is executed in the context of the event
327  * queue's dispatch loop.
328  *
329  * The call function is IRQ safe and can act as a mechanism for moving
330  * events out of IRQ contexts.
331  *
332  * @param obj Object to call with the member function
333  * @param method Member function to execute in the context of the dispatch loop
334  * @param args Arguments to pass to the callback
335  * @return A unique ID that represents the posted event and can
336  * be passed to cancel, or an ID of 0 if there is not
337  * enough memory to allocate the event.
338  * Returned ID remains valid until event has finished
339  * executing.
340  *
341  * @code
342  * #include "mbed.h"
343  *
344  * class EventHandler {
345  * int _id;
346  * public:
347  * EventHandler(int id) : _id(id) { }
348  *
349  * void handler(int c) {
350  * printf("ID: %d Param: %d\r\n", _id, c);
351  * }
352  * };
353  *
354  * int main() {
355  * // creates a queue with the default size
356  * EventQueue queue;
357  *
358  * // Create EventHandler object with state
359  * EventHandler handler_cb(1);
360  *
361  * // events are simple callbacks, call object method
362  * // with provided parameter
363  * queue.call(&handler_cb, &EventHandler::handler, 2);
364  *
365  * // the dispath method executes events
366  * queue.dispatch();
367  * }
368  * @endcode
369  */
370  // AStyle ignore, not handling correctly below
371  // *INDENT-OFF*
372  template <typename T, typename R, typename ...Args>
373  int call(T *obj, R (T::*method)(Args ...args), Args ...args);
374  // *INDENT-ON*
375 
376  /** Calls an event on the queue after a specified delay
377  *
378  * The specified callback is executed in the context of the event
379  * queue's dispatch loop.
380  *
381  * The call_in function is IRQ safe and can act as a mechanism for moving
382  * events out of IRQ contexts.
383  *
384  * @param ms Time to delay in milliseconds
385  * @param f Function to execute in the context of the dispatch loop
386  * @param args Arguments to pass to the callback
387  * @return A unique ID that represents the posted event and can
388  * be passed to cancel, or an ID of 0 if there is not
389  * enough memory to allocate the event.
390  *
391  * @code
392  * #include "mbed.h"
393  * using namespace std::chrono_literals;
394  *
395  * int main() {
396  * // creates a queue with the default size
397  * EventQueue queue;
398  *
399  * // events are simple callbacks
400  * queue.call_in(2s, printf, "called in 2 seconds\n");
401  *
402  * // the dispatch methods executes events
403  * queue.dispatch();
404  * }
405  * @endcode
406  */
407  template <typename F, typename ...ArgTs>
408  int call_in(duration ms, F f, ArgTs ...args);
409 
410  /** Calls an event on the queue after a specified delay
411  *
412  * The specified callback is executed in the context of the event
413  * queue's dispatch loop.
414  *
415  * The call_in function is IRQ safe and can act as a mechanism for moving
416  * events out of IRQ contexts.
417  *
418  * @param ms Time to delay in milliseconds
419  * @param obj Object to call with the member function
420  * @param method Member function to execute in the context of the dispatch loop
421  * @param args Arguments to pass to the callback
422  * @return A unique ID that represents the posted event and can
423  * be passed to cancel, or an ID of 0 if there is not
424  * enough memory to allocate the event.
425  *
426  * @code
427  * #include "mbed.h"
428  * using namespace std::chrono_literals;
429  *
430  * class EventHandler {
431  * int _id;
432  * public:
433  * EventHandler(int id) : _id(id) { }
434  *
435  * void handler(int c) {
436  * printf("ID: %d Param: %d\r\n", _id, c);
437  * }
438  * };
439  *
440  * int main() {
441  * // creates a queue with the default size
442  * EventQueue queue;
443  *
444  * // Create EventHandler object with state
445  * EventHandler handler_cb(3);
446  *
447  * // events are simple callbacks, call object method in 2 seconds
448  * // with provided parameter
449  * queue.call_in(2s, &handler_cb, &EventHandler::handler, 4);
450  *
451  * // the dispatch method executes events
452  * queue.dispatch();
453  * }
454  * @endcode
455  */
456  // AStyle ignore, not handling correctly below
457  // *INDENT-OFF*
458  template <typename T, typename R, typename ...ArgTs>
459  int call_in(duration ms, T *obj, R (T::*method)(ArgTs ...args), ArgTs ...args);
460  // *INDENT-ON*
461 
462  /** Calls an event on the queue periodically
463  *
464  * @note The first call_every event occurs after the specified delay.
465  * To create a periodic event that fires immediately, @see Event.
466  *
467  * The specified callback is executed in the context of the event
468  * queue's dispatch loop.
469  *
470  * The call_every function is IRQ safe and can act as a mechanism for
471  * moving events out of IRQ contexts.
472  *
473  * @param ms Period of the event in milliseconds
474  * @param f Function to execute in the context of the dispatch loop
475  * @param args Arguments to pass to the callback
476  * @return A unique ID that represents the posted event and can
477  * be passed to cancel, or an ID of 0 if there is not
478  * enough memory to allocate the event.
479  *
480  * @code
481  * #include "mbed.h"
482  * using namespace std::chrono_literals;
483  *
484  * class EventHandler {
485  * int _id;
486  * public:
487  * EventHandler(int id) : _id(id) { }
488  *
489  * void handler(int c) {
490  * printf("ID: %d Param: %d\r\n", _id, c);
491  * }
492  * };
493  *
494  * int main() {
495  * // creates a queue with the default size
496  * EventQueue queue;
497  *
498  * // events are simple callbacks, call every 2 seconds
499  * queue.call_every(2s, printf, "Calling every 2 seconds\n");
500  *
501  * // the dispatch method executes events
502  * queue.dispatch();
503  * }
504  * @endcode
505  */
506  template <typename F, typename ...ArgTs>
507  int call_every(duration ms, F f, ArgTs ...args);
508 
509  /** Calls an event on the queue periodically
510  *
511  * @note The first call_every event occurs after the specified delay.
512  * To create a periodic event that fires immediately, @see Event.
513  *
514  * The specified callback is executed in the context of the event
515  * queue's dispatch loop.
516  *
517  * The call_every function is IRQ safe and can act as a mechanism for
518  * moving events out of IRQ contexts.
519  *
520  * @param ms Period of the event in milliseconds
521  * @param obj Object to call with the member function
522  * @param method Member function to execute in the context of the dispatch loop
523  * @param args Arguments to pass to the callback
524  *
525  * @code
526  * #include "mbed.h"
527  * using namespace std::chrono_literals;
528  *
529  * class EventHandler {
530  * int _id;
531  * public:
532  * EventHandler(int id) : _id(id) { }
533  *
534  * void handler(int c) {
535  * printf("ID: %d Param: %d\r\n", _id, c);
536  * }
537  * };
538  *
539  * int main() {
540  * // creates a queue with the default size
541  * EventQueue queue;
542  *
543  * // Create EventHandler object with state
544  * EventHandler handler_cb(5);
545  *
546  * // events are simple callbacks, call object method every 2 seconds
547  * // with provided parameter
548  * queue.call_every(2s, &handler_cb, &EventHandler::handler, 6);
549  *
550  * // the dispatch method executes events
551  * queue.dispatch();
552  * }
553  * @endcode
554  */
555  // AStyle ignore, not handling correctly below
556  // *INDENT-OFF*
557  template <typename T, typename R, typename ...ArgTs>
558  int call_every(duration ms, T *obj, R (T::*method)(ArgTs ...args), ArgTs ...args);
559  // *INDENT-ON*
560 
561  /** Creates an event bound to the event queue
562  *
563  * Constructs an event bound to the specified event queue. The specified
564  * callback acts as the target for the event and is executed in the
565  * context of the event queue's dispatch loop once posted.
566  *
567  * @param func Function to execute when the event is dispatched
568  * @param context_args Arguments to pass to the callback
569  * @return Event that dispatches on the specific queue
570  *
571  * @code
572  * #include "mbed.h"
573  *
574  * void handler(int c) {
575  * printf("Param: %d\r\n", c);
576  * }
577  *
578  * int main()
579  * {
580  * EventQueue queue;
581  *
582  * // Create event with parameter
583  * Event<void()> e = queue.event(handler, 1);
584  * e();
585  *
586  * // Create event and post parameter later
587  * Event<void(int)> e2 = queue.event(handler);
588  *
589  * // Post the event with paramter 8
590  * e.post(8);
591  *
592  * // The dispatch method executes events
593  * queue.dispatch();
594  *
595  * e2.post(2);
596  *
597  * queue.dispatch();
598  * }
599  * @endcode
600  */
601  // AStyle ignore, not handling correctly below
602  // *INDENT-OFF*
603  template <typename R, typename ...BoundArgTs, typename ...ContextArgTs, typename ...ArgTs>
604  Event<void(ArgTs...)> event(R (*func)(BoundArgTs..., ArgTs...), ContextArgTs ...context_args);
605  // *INDENT-ON*
606 
607  /** Creates an event bound to the event queue
608  *
609  * Constructs an event bound to the specified event queue. The specified
610  * callback acts as the target for the event and is executed in the
611  * context of the event queue's dispatch loop once posted.
612  *
613  * @param obj Object to call with the member function
614  * @param method Member function to execute in the context of the dispatch loop
615  * @param context_args Arguments to pass to the callback
616  * @return Event that dispatches on the specific queue
617  *
618  * @code
619  * #include "mbed.h"
620  *
621  * class EventHandler {
622  * int _id;
623  *
624  * public:
625  * EventHandler(int id) : _id(id) { }
626  *
627  * void handler(int c) {
628  * printf("ID: %d Param: %d\r\n", _id, c);
629  * }
630  * };
631  *
632  * int main()
633  * {
634  * EventQueue queue;
635  *
636  * EventHandler handler_cb(10);
637  *
638  * // Create event on the eventqueue with a method callback
639  * Event<void(int)> e = queue.event(&handler_cb, &EventHandler::handler);
640  *
641  * // Post the event with paramter 8
642  * e.post(11);
643  *
644  * // The dispatch method executes events
645  * queue.dispatch();
646  * }
647  * @endcode
648  */
649  // AStyle ignore, not handling correctly below
650  // *INDENT-OFF*
651  template <typename T, typename R, typename ...BoundArgTs, typename ...ContextArgTs, typename ...ArgTs>
652  Event<void(ArgTs...)> event(T *obj, R (T::*method)(BoundArgTs..., ArgTs...), ContextArgTs ...context_args);
653  // *INDENT-ON*
654 
655  /** Creates an event bound to the event queue
656  *
657  * Constructs an event bound to the specified event queue. The specified
658  * callback acts as the target for the event and is executed in the
659  * context of the event queue's dispatch loop once posted.
660  *
661  * @param cb Callback object
662  * @param context_args Arguments to pass to the callback
663  * @return Event that dispatches on the specific queue
664  *
665  * @code
666  * #include "mbed.h"
667  *
668  * void handler(int c) {
669  * printf("Param: %d\r\n", c);
670  * }
671  *
672  * int main()
673  * {
674  * EventQueue queue;
675  * // Create callback object acting as a function
676  * // pointer to handler
677  * Callback<void(int)> cb(handler);
678  *
679  * // Pass the callback object to the eventqueue
680  * Event<void(int)> e = queue.event(cb);
681  *
682  * // Post the event with parameter 8
683  * e.post(9);
684  *
685  * // The dispatch method executes events
686  * q.dispatch();
687  * }
688  * @endcode
689  */
690  template <typename R, typename ...BoundArgTs, typename ...ContextArgTs, typename ...ArgTs>
691  Event<void(ArgTs...)> event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, ContextArgTs ...context_args);
692 
693  /** Creates an user allocated event bound to the event queue
694  *
695  * Constructs an user allocated event bound to the specified event queue.
696  * The specified callback acts as the target for the event and is executed
697  * in the context of the event queue's dispatch loop once posted.
698  *
699  * @code
700  * #include "mbed.h"
701  *
702  * void handler(int data) { ... }
703  *
704  * class Device {
705  * public:
706  * void handler(int data) { ... }
707  * };
708  *
709  * Device dev;
710  *
711  * // queue with not internal storage for dynamic events
712  * // accepts only user allocated events
713  * static EventQueue queue(0);
714  * // Create events
715  * static auto e1 = make_user_allocated_event(&dev, Device::handler, 2);
716  * static auto e2 = queue.make_user_allocated_event(handler, 3);
717  *
718  * int main()
719  * {
720  * e1.call_on(&queue);
721  * e2.call();
722  *
723  * queue.dispatch(1);
724  * }
725  * @endcode
726  *
727  * @param f Function to execute when the event is dispatched
728  * @return Event that will dispatch on the specific queue
729  */
730  template <typename F, typename... ArgTs>
731  UserAllocatedEvent<F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs... args);
732 
733  /** Creates an user allocated event bound to the event queue
734  * @see EventQueue::make_user_allocated_event
735  */
736  template <typename T, typename R, typename... ArgTs>
737  UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
738 
739 
740 #else
741 
742  /** Calls an event on the queue
743  *
744  * The specified callback is executed in the context of the event
745  * queue's dispatch loop.
746  *
747  * The call function is IRQ safe and can act as a mechanism for moving
748  * events out of IRQ contexts.
749  *
750  * @param f Function to execute in the context of the dispatch loop
751  * @return A unique ID that represents the posted event and can
752  * be passed to cancel, or an ID of 0 if there is not
753  * enough memory to allocate the event.
754  * Returned ID remains valid until event has finished
755  * executing.
756  *
757  * @code
758  * #include "mbed.h"
759  *
760  * int main()
761  * {
762  * EventQueue queue;
763  *
764  * Callback<void(int)> cb(handler);
765  *
766  * // Create event on the eventqueue with a separate callback object
767  * Event<void(int)> e = queue.event(cb);
768  * e.post(1);
769  * queue.dispatch();
770  * }
771  * @endcode
772  */
773  template <typename F>
774  int call(F f)
775  {
776  void *p = equeue_alloc(&_equeue, sizeof(F));
777  if (!p) {
778  return 0;
779  }
780 
781  F *e = new (p) F(std::move(f));
782  equeue_event_dtor(e, &EventQueue::function_dtor<F>);
783  return equeue_post(&_equeue, &EventQueue::function_call<F>, e);
784  }
785 
786 
787  /** Calls an event on the queue
788  * @see EventQueue::call
789  * @param f Function to execute in the context of the dispatch loop
790  * @param args Arguments to pass to the callback
791  */
792  template <typename F, typename... ArgTs>
793  int call(F f, ArgTs... args)
794  {
795  return call(context<F, ArgTs...>(std::move(f), args...));
796  }
797 
798  /** Calls an event on the queue
799  * @see EventQueue::call
800  */
801  template <typename T, typename R, typename... ArgTs>
802  int call(T *obj, R(T::*method)(ArgTs...), ArgTs... args)
803  {
804  return call(mbed::callback(obj, method), args...);
805  }
806 
807  /** Calls an event on the queue
808  * @see EventQueue::call
809  */
810  template <typename T, typename R, typename... ArgTs>
811  int call(const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
812  {
813  return call(mbed::callback(obj, method), args...);
814  }
815 
816  /** Calls an event on the queue
817  * @see EventQueue::call
818  */
819  template <typename T, typename R, typename... ArgTs>
820  int call(volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
821  {
822  return call(mbed::callback(obj, method), args...);
823  }
824 
825  /** Calls an event on the queue
826  * @see EventQueue::call
827  */
828  template <typename T, typename R, typename... ArgTs>
829  int call(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
830  {
831  return call(mbed::callback(obj, method), args...);
832  }
833 
834  /** Calls an event on the queue after a specified delay
835  *
836  * The specified callback will be executed in the context of the event
837  * queue's dispatch loop.
838  *
839  * The call_in function is IRQ safe and can act as a mechanism for moving
840  * events out of IRQ contexts.
841  *
842  * @param ms Time to delay in milliseconds
843  * @param f Function to execute in the context of the dispatch loop
844  * @return A unique id that represents the posted event and can
845  * be passed to cancel, or an id of 0 if there is not
846  * enough memory to allocate the event.
847  */
848  template <typename F>
849  int call_in(duration ms, F f)
850  {
851  void *p = equeue_alloc(&_equeue, sizeof(F));
852  if (!p) {
853  return 0;
854  }
855 
856  F *e = new (p) F(std::move(f));
857  equeue_event_delay(e, ms.count());
858  equeue_event_dtor(e, &EventQueue::function_dtor<F>);
859  return equeue_post(&_equeue, &EventQueue::function_call<F>, e);
860  }
861 
862  /** Calls an event on the queue after a specified delay
863  * @see EventQueue::call_in
864  * @param ms Time to delay in milliseconds
865  * @param f Function to execute in the context of the dispatch loop
866  * @param args Arguments to pass to the callback
867  */
868  template <typename F, typename... ArgTs>
869  int call_in(duration ms, F f, ArgTs... args)
870  {
871  return call_in(ms, context<F, ArgTs...>(std::move(f), args...));
872  }
873 
874  /** Calls an event on the queue after a specified delay
875  * @see EventQueue::call_in
876  */
877  template <typename T, typename R, typename... ArgTs>
878  int call_in(duration ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
879  {
880  return call_in(ms, mbed::callback(obj, method), args...);
881  }
882 
883  /** Calls an event on the queue after a specified delay
884  * @see EventQueue::call_in
885  */
886  template <typename T, typename R, typename... ArgTs>
887  int call_in(duration ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
888  {
889  return call_in(ms, mbed::callback(obj, method), args...);
890  }
891 
892  /** Calls an event on the queue after a specified delay
893  * @see EventQueue::call_in
894  */
895  template <typename T, typename R, typename... ArgTs>
896  int call_in(duration ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
897  {
898  return call_in(ms, mbed::callback(obj, method), args...);
899  }
900 
901  /** Calls an event on the queue after a specified delay
902  * @see EventQueue::call_in
903  */
904  template <typename T, typename R, typename... ArgTs>
905  int call_in(duration ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
906  {
907  return call_in(ms, mbed::callback(obj, method), args...);
908  }
909 
910  /** Calls an event on the queue after a specified delay
911  *
912  * The specified callback will be executed in the context of the event
913  * queue's dispatch loop.
914  *
915  * The call_in function is IRQ safe and can act as a mechanism for moving
916  * events out of IRQ contexts.
917  *
918  * @param ms Time to delay in milliseconds
919  * @param f Function to execute in the context of the dispatch loop
920  * @return A unique id that represents the posted event and can
921  * be passed to cancel, or an id of 0 if there is not
922  * enough memory to allocate the event.
923  */
924  template <typename F>
925  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
926  int call_in(int ms, F f)
927  {
928  return call_in(duration(ms), std::move(f));
929  }
930 
931  /** Calls an event on the queue after a specified delay
932  * @see EventQueue::call_in
933  * @param ms Time to delay in milliseconds
934  * @param f Function to execute in the context of the dispatch loop
935  * @param args Arguments to pass to the callback
936  */
937  template <typename F, typename... ArgTs>
938  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
939  int call_in(int ms, F f, ArgTs... args)
940  {
941  return call_in(duration(ms), std::move(f), args...);
942  }
943 
944  /** Calls an event on the queue after a specified delay
945  * @see EventQueue::call_in
946  */
947  template <typename T, typename R, typename... ArgTs>
948  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
949  int call_in(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
950  {
951  return call_in(duration(ms), obj, method, args...);
952  }
953 
954  /** Calls an event on the queue after a specified delay
955  * @see EventQueue::call_in
956  */
957  template <typename T, typename R, typename... ArgTs>
958  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
959  int call_in(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
960  {
961  return call_in(duration(ms), obj, method, args...);
962  }
963 
964  /** Calls an event on the queue after a specified delay
965  * @see EventQueue::call_in
966  */
967  template <typename T, typename R, typename... ArgTs>
968  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
969  int call_in(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
970  {
971  return call_in(duration(ms), obj, method, args...);
972  }
973 
974  /** Calls an event on the queue after a specified delay
975  * @see EventQueue::call_in
976  */
977  template <typename T, typename R, typename... ArgTs>
978  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
979  int call_in(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
980  {
981  return call_in(duration(ms), obj, method, args...);
982  }
983 
984  /** Calls an event on the queue periodically
985  *
986  * @note The first call_every event occurs after the specified delay.
987  * To create a periodic event that fires immediately, @see Event.
988  *
989  * The specified callback will be executed in the context of the event
990  * queue's dispatch loop.
991  *
992  * The call_every function is IRQ safe and can act as a mechanism for
993  * moving events out of IRQ contexts.
994  *
995  * @param f Function to execute in the context of the dispatch loop
996  * @param ms Period of the event in milliseconds
997  * @return A unique id that represents the posted event and can
998  * be passed to cancel, or an id of 0 if there is not
999  * enough memory to allocate the event.
1000  */
1001  template <typename F>
1002  int call_every(duration ms, F f)
1003  {
1004  void *p = equeue_alloc(&_equeue, sizeof(F));
1005  if (!p) {
1006  return 0;
1007  }
1008 
1009  F *e = new (p) F(std::move(f));
1010  equeue_event_delay(e, ms.count());
1011  equeue_event_period(e, ms.count());
1012  equeue_event_dtor(e, &EventQueue::function_dtor<F>);
1013  return equeue_post(&_equeue, &EventQueue::function_call<F>, e);
1014  }
1015 
1016  /** Calls an event on the queue periodically
1017  * @see EventQueue::call_every
1018  * @param f Function to execute in the context of the dispatch loop
1019  * @param args Arguments to pass to the callback
1020  * @param ms Period of the event in milliseconds
1021  */
1022  template <typename F, typename... ArgTs>
1023  int call_every(duration ms, F f, ArgTs... args)
1024  {
1025  return call_every(ms, context<F, ArgTs...>(std::move(f), args...));
1026  }
1027 
1028  /** Calls an event on the queue periodically
1029  * @see EventQueue::call_every
1030  */
1031  template <typename T, typename R, typename... ArgTs>
1032  int call_every(duration ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
1033  {
1034  return call_every(ms, mbed::callback(obj, method), args...);
1035  }
1036 
1037  /** Calls an event on the queue periodically
1038  * @see EventQueue::call_every
1039  */
1040  template <typename T, typename R, typename... ArgTs>
1041  int call_every(duration ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
1042  {
1043  return call_every(ms, mbed::callback(obj, method), args...);
1044  }
1045 
1046  /** Calls an event on the queue periodically
1047  * @see EventQueue::call_every
1048  */
1049  template <typename T, typename R, typename... ArgTs>
1050  int call_every(duration ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
1051  {
1052  return call_every(ms, mbed::callback(obj, method), args...);
1053  }
1054 
1055  /** Calls an event on the queue periodically
1056  * @see EventQueue::call_every
1057  */
1058  template <typename T, typename R, typename... ArgTs>
1059  int call_every(duration ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
1060  {
1061  return call_every(ms, mbed::callback(obj, method), args...);
1062  }
1063 
1064  /** Calls an event on the queue periodically
1065  *
1066  * @note The first call_every event occurs after the specified delay.
1067  * To create a periodic event that fires immediately, @see Event.
1068  *
1069  * The specified callback will be executed in the context of the event
1070  * queue's dispatch loop.
1071  *
1072  * The call_every function is IRQ safe and can act as a mechanism for
1073  * moving events out of IRQ contexts.
1074  *
1075  * @param f Function to execute in the context of the dispatch loop
1076  * @param ms Period of the event in milliseconds
1077  * @return A unique id that represents the posted event and can
1078  * be passed to cancel, or an id of 0 if there is not
1079  * enough memory to allocate the event.
1080  */
1081  template <typename F>
1082  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1083  int call_every(int ms, F f)
1084  {
1085  return call_every(duration(ms), std::move(f));
1086  }
1087 
1088  /** Calls an event on the queue periodically
1089  * @see EventQueue::call_every
1090  * @param f Function to execute in the context of the dispatch loop
1091  * @param args Arguments to pass to the callback
1092  * @param ms Period of the event in milliseconds
1093  */
1094  template <typename F, typename... ArgTs>
1095  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1096  int call_every(int ms, F f, ArgTs... args)
1097  {
1098  return call_every(duration(ms), std::move(f), args...);
1099  }
1100 
1101  /** Calls an event on the queue periodically
1102  * @see EventQueue::call_every
1103  */
1104  template <typename T, typename R, typename... ArgTs>
1105  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1106  int call_every(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
1107  {
1108  return call_every(duration(ms), obj, method, args...);
1109  }
1110 
1111  /** Calls an event on the queue periodically
1112  * @see EventQueue::call_every
1113  */
1114  template <typename T, typename R, typename... ArgTs>
1115  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1116  int call_every(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
1117  {
1118  return call_every(duration(ms), obj, method, args...);
1119  }
1120 
1121  /** Calls an event on the queue periodically
1122  * @see EventQueue::call_every
1123  */
1124  template <typename T, typename R, typename... ArgTs>
1125  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1126  int call_every(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
1127  {
1128  return call_every(duration(ms), obj, method, args...);
1129  }
1130 
1131  /** Calls an event on the queue periodically
1132  * @see EventQueue::call_every
1133  */
1134  template <typename T, typename R, typename... ArgTs>
1135  MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
1136  int call_every(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
1137  {
1138  return call_every(duration(ms), obj, method, args...);
1139  }
1140 
1141  /** Creates an event bound to the event queue
1142  *
1143  * Constructs an event bound to the specified event queue. The specified
1144  * callback acts as the target for the event and is executed in the
1145  * context of the event queue's dispatch loop once posted.
1146  *
1147  * @param func Function to execute when the event is dispatched
1148  * @return Event that will dispatch on the specific queue
1149  */
1150  template <typename R, typename... ArgTs>
1151  Event<void(ArgTs...)> event(R(*func)(ArgTs...));
1152 
1153  /** Creates an event bound to the event queue
1154  * @see EventQueue::event
1155  */
1156  template <typename T, typename R, typename... ArgTs>
1157  Event<void(ArgTs...)> event(T *obj, R(T::*method)(ArgTs...));
1158 
1159  /** Creates an event bound to the event queue
1160  * @see EventQueue::event
1161  */
1162  template <typename T, typename R, typename... ArgTs>
1163  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(ArgTs...) const);
1164 
1165  /** Creates an event bound to the event queue
1166  * @see EventQueue::event
1167  */
1168  template <typename T, typename R, typename... ArgTs>
1169  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(ArgTs...) volatile);
1170 
1171  /** Creates an event bound to the event queue
1172  * @see EventQueue::event
1173  */
1174  template <typename T, typename R, typename... ArgTs>
1175  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(ArgTs...) const volatile);
1176 
1177  /** Creates an event bound to the event queue
1178  * @see EventQueue::event
1179  */
1180  template <typename R, typename... ArgTs>
1181  Event<void(ArgTs...)> event(mbed::Callback<R(ArgTs...)> cb);
1182 
1183  /** Creates an event bound to the event queue
1184  * @see EventQueue::event
1185  */
1186  template <typename R, typename B0, typename C0, typename... ArgTs>
1187  Event<void(ArgTs...)> event(R(*func)(B0, ArgTs...), C0 c0);
1188 
1189  /** Creates an event bound to the event queue
1190  * @see EventQueue::event
1191  */
1192  template <typename T, typename R, typename B0, typename C0, typename... ArgTs>
1193  Event<void(ArgTs...)> event(T *obj, R(T::*method)(B0, ArgTs...), C0 c0);
1194 
1195  /** Creates an event bound to the event queue
1196  * @see EventQueue::event
1197  */
1198  template <typename T, typename R, typename B0, typename C0, typename... ArgTs>
1199  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(B0, ArgTs...) const, C0 c0);
1200 
1201  /** Creates an event bound to the event queue
1202  * @see EventQueue::event
1203  */
1204  template <typename T, typename R, typename B0, typename C0, typename... ArgTs>
1205  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(B0, ArgTs...) volatile, C0 c0);
1206 
1207  /** Creates an event bound to the event queue
1208  * @see EventQueue::event
1209  */
1210  template <typename T, typename R, typename B0, typename C0, typename... ArgTs>
1211  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(B0, ArgTs...) const volatile, C0 c0);
1212 
1213  /** Creates an event bound to the event queue
1214  * @see EventQueue::event
1215  */
1216  template <typename R, typename B0, typename C0, typename... ArgTs>
1217  Event<void(ArgTs...)> event(mbed::Callback<R(B0, ArgTs...)> cb, C0 c0);
1218 
1219  /** Creates an event bound to the event queue
1220  * @see EventQueue::event
1221  */
1222  template <typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1223  Event<void(ArgTs...)> event(R(*func)(B0, B1, ArgTs...), C0 c0, C1 c1);
1224 
1225  /** Creates an event bound to the event queue
1226  * @see EventQueue::event
1227  */
1228  template <typename T, typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1229  Event<void(ArgTs...)> event(T *obj, R(T::*method)(B0, B1, ArgTs...), C0 c0, C1 c1);
1230 
1231  /** Creates an event bound to the event queue
1232  * @see EventQueue::event
1233  */
1234  template <typename T, typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1235  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(B0, B1, ArgTs...) const, C0 c0, C1 c1);
1236 
1237  /** Creates an event bound to the event queue
1238  * @see EventQueue::event
1239  */
1240  template <typename T, typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1241  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(B0, B1, ArgTs...) volatile, C0 c0, C1 c1);
1242 
1243  /** Creates an event bound to the event queue
1244  * @see EventQueue::event
1245  */
1246  template <typename T, typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1247  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(B0, B1, ArgTs...) const volatile, C0 c0, C1 c1);
1248 
1249  /** Creates an event bound to the event queue
1250  * @see EventQueue::event
1251  */
1252  template <typename R, typename B0, typename B1, typename C0, typename C1, typename... ArgTs>
1253  Event<void(ArgTs...)> event(mbed::Callback<R(B0, B1, ArgTs...)> cb, C0 c0, C1 c1);
1254 
1255  /** Creates an event bound to the event queue
1256  * @see EventQueue::event
1257  */
1258  template <typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1259  Event<void(ArgTs...)> event(R(*func)(B0, B1, B2, ArgTs...), C0 c0, C1 c1, C2 c2);
1260 
1261  /** Creates an event bound to the event queue
1262  * @see EventQueue::event
1263  */
1264  template <typename T, typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1265  Event<void(ArgTs...)> event(T *obj, R(T::*method)(B0, B1, B2, ArgTs...), C0 c0, C1 c1, C2 c2);
1266 
1267  /** Creates an event bound to the event queue
1268  * @see EventQueue::event
1269  */
1270  template <typename T, typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1271  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(B0, B1, B2, ArgTs...) const, C0 c0, C1 c1, C2 c2);
1272 
1273  /** Creates an event bound to the event queue
1274  * @see EventQueue::event
1275  */
1276  template <typename T, typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1277  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(B0, B1, B2, ArgTs...) volatile, C0 c0, C1 c1, C2 c2);
1278 
1279  /** Creates an event bound to the event queue
1280  * @see EventQueue::event
1281  */
1282  template <typename T, typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1283  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(B0, B1, B2, ArgTs...) const volatile, C0 c0, C1 c1, C2 c2);
1284 
1285  /** Creates an event bound to the event queue
1286  * @see EventQueue::event
1287  */
1288  template <typename R, typename B0, typename B1, typename B2, typename C0, typename C1, typename C2, typename... ArgTs>
1289  Event<void(ArgTs...)> event(mbed::Callback<R(B0, B1, B2, ArgTs...)> cb, C0 c0, C1 c1, C2 c2);
1290 
1291  /** Creates an event bound to the event queue
1292  * @see EventQueue::event
1293  */
1294  template <typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1295  Event<void(ArgTs...)> event(R(*func)(B0, B1, B2, B3, ArgTs...), C0 c0, C1 c1, C2 c2, C3 c3);
1296 
1297  /** Creates an event bound to the event queue
1298  * @see EventQueue::event
1299  */
1300  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1301  Event<void(ArgTs...)> event(T *obj, R(T::*method)(B0, B1, B2, B3, ArgTs...), C0 c0, C1 c1, C2 c2, C3 c3);
1302 
1303  /** Creates an event bound to the event queue
1304  * @see EventQueue::event
1305  */
1306  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1307  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(B0, B1, B2, B3, ArgTs...) const, C0 c0, C1 c1, C2 c2, C3 c3);
1308 
1309  /** Creates an event bound to the event queue
1310  * @see EventQueue::event
1311  */
1312  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1313  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(B0, B1, B2, B3, ArgTs...) volatile, C0 c0, C1 c1, C2 c2, C3 c3);
1314 
1315  /** Creates an event bound to the event queue
1316  * @see EventQueue::event
1317  */
1318  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1319  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(B0, B1, B2, B3, ArgTs...) const volatile, C0 c0, C1 c1, C2 c2, C3 c3);
1320 
1321  /** Creates an event bound to the event queue
1322  * @see EventQueue::event
1323  */
1324  template <typename R, typename B0, typename B1, typename B2, typename B3, typename C0, typename C1, typename C2, typename C3, typename... ArgTs>
1325  Event<void(ArgTs...)> event(mbed::Callback<R(B0, B1, B2, B3, ArgTs...)> cb, C0 c0, C1 c1, C2 c2, C3 c3);
1326 
1327  /** Creates an event bound to the event queue
1328  * @see EventQueue::event
1329  */
1330  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>
1331  Event<void(ArgTs...)> event(R(*func)(B0, B1, B2, B3, B4, ArgTs...), C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1332 
1333  /** Creates an event bound to the event queue
1334  * @see EventQueue::event
1335  */
1336  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename B4, typename C0, typename C1, typename C2, typename C3, typename C4, typename... ArgTs>
1337  Event<void(ArgTs...)> event(T *obj, R(T::*method)(B0, B1, B2, B3, B4, ArgTs...), C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1338 
1339  /** Creates an event bound to the event queue
1340  * @see EventQueue::event
1341  */
1342  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename B4, typename C0, typename C1, typename C2, typename C3, typename C4, typename... ArgTs>
1343  Event<void(ArgTs...)> event(const T *obj, R(T::*method)(B0, B1, B2, B3, B4, ArgTs...) const, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1344 
1345  /** Creates an event bound to the event queue
1346  * @see EventQueue::event
1347  */
1348  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename B4, typename C0, typename C1, typename C2, typename C3, typename C4, typename... ArgTs>
1349  Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(B0, B1, B2, B3, B4, ArgTs...) volatile, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1350 
1351  /** Creates an event bound to the event queue
1352  * @see EventQueue::event
1353  */
1354  template <typename T, typename R, typename B0, typename B1, typename B2, typename B3, typename B4, typename C0, typename C1, typename C2, typename C3, typename C4, typename... ArgTs>
1355  Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(B0, B1, B2, B3, B4, ArgTs...) const volatile, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1356 
1357  /** Creates an event bound to the event queue
1358  * @see EventQueue::event
1359  */
1360  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>
1361  Event<void(ArgTs...)> event(mbed::Callback<R(B0, B1, B2, B3, B4, ArgTs...)> cb, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
1362 
1363  /** Creates an user allocated event bound to the event queue
1364  *
1365  * Constructs an user allocated event bound to the specified event queue.
1366  * The specified callback acts as the target for the event and is executed
1367  * in the context of the event queue's dispatch loop once posted.
1368  *
1369  * @param f Function to execute when the event is dispatched
1370  * @return Event that will dispatch on the specific queue
1371  */
1372  template <typename F, typename... ArgTs>
1373  UserAllocatedEvent<F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs... args);
1374 
1375  /** Creates an user allocated event bound to the event queue
1376  * @see EventQueue::make_user_allocated_event
1377  */
1378  template <typename T, typename R, typename... ArgTs>
1379  UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
1380 
1381  /** Creates an user allocated event bound to the event queue
1382  * @see EventQueue::make_user_allocated_event
1383  */
1384  template <typename T, typename R, typename... ArgTs>
1385  UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const T *obj, R(T::*method)(ArgTs... args) const, ArgTs... args);
1386 
1387  /** Creates an user allocated event bound to the event queue
1388  * @see EventQueue::make_user_allocated_event
1389  */
1390  template <typename T, typename R, typename... ArgTs>
1391  UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(volatile T *obj, R(T::*method)(ArgTs... args) volatile, ArgTs... args);
1392 
1393  /** Creates an user allocated event bound to the event queue
1394  * @see EventQueue::make_user_allocated_event
1395  */
1396  template <typename T, typename R, typename... ArgTs>
1397  UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const volatile T *obj, R(T::*method)(ArgTs... args) const volatile, ArgTs... args);
1398 #endif
1399 
1400 protected:
1401 #if !defined(DOXYGEN_ONLY)
1402  template <typename F>
1403  friend class Event;
1404  template <typename F, typename A>
1405  friend class UserAllocatedEvent;
1406  struct equeue _equeue;
1407  mbed::Callback<void(int)> _update;
1408 
1409  // Function attributes
1410  template <typename F>
1411  static void function_call(void *p)
1412  {
1413  (*(F *)p)();
1414  }
1415 
1416  template <typename F>
1417  static void function_dtor(void *p)
1418  {
1419  ((F *)p)->~F();
1420  }
1421 
1422  // Context structures
1423  template <typename F, typename... ContextArgTs>
1424  struct context;
1425 
1426  template <typename F>
1427  struct context<F> {
1428  F f;
1429 
1430  constexpr context(F f)
1431  : f(f) {}
1432 
1433  template <typename... ArgTs>
1434  void operator()(ArgTs... args)
1435  {
1436  f(args...);
1437  }
1438  };
1439 
1440  template <typename F, typename C0>
1441  struct context<F, C0> {
1442  F f;
1443  C0 c0;
1444 
1445  constexpr context(F f, C0 c0)
1446  : f(f), c0(c0) {}
1447 
1448  template <typename... ArgTs>
1449  void operator()(ArgTs... args)
1450  {
1451  f(c0, args...);
1452  }
1453  };
1454 
1455  template <typename F, typename C0, typename C1>
1456  struct context<F, C0, C1> {
1457  F f;
1458  C0 c0;
1459  C1 c1;
1460 
1461  constexpr context(F f, C0 c0, C1 c1)
1462  : f(f), c0(c0), c1(c1) {}
1463 
1464  template <typename... ArgTs>
1465  void operator()(ArgTs... args)
1466  {
1467  f(c0, c1, args...);
1468  }
1469  };
1470 
1471  template <typename F, typename C0, typename C1, typename C2>
1472  struct context<F, C0, C1, C2> {
1473  F f;
1474  C0 c0;
1475  C1 c1;
1476  C2 c2;
1477 
1478  constexpr context(F f, C0 c0, C1 c1, C2 c2)
1479  : f(f), c0(c0), c1(c1), c2(c2) {}
1480 
1481  template <typename... ArgTs>
1482  void operator()(ArgTs... args)
1483  {
1484  f(c0, c1, c2, args...);
1485  }
1486  };
1487 
1488  template <typename F, typename C0, typename C1, typename C2, typename C3>
1489  struct context<F, C0, C1, C2, C3> {
1490  F f;
1491  C0 c0;
1492  C1 c1;
1493  C2 c2;
1494  C3 c3;
1495 
1496  constexpr context(F f, C0 c0, C1 c1, C2 c2, C3 c3)
1497  : f(f), c0(c0), c1(c1), c2(c2), c3(c3) {}
1498 
1499  template <typename... ArgTs>
1500  void operator()(ArgTs... args)
1501  {
1502  f(c0, c1, c2, c3, args...);
1503  }
1504  };
1505 
1506  template <typename F, typename C0, typename C1, typename C2, typename C3, typename C4>
1507  struct context<F, C0, C1, C2, C3, C4> {
1508  F f;
1509  C0 c0;
1510  C1 c1;
1511  C2 c2;
1512  C3 c3;
1513  C4 c4;
1514 
1515  constexpr context(F f, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4)
1516  : f(f), c0(c0), c1(c1), c2(c2), c3(c3), c4(c4) {}
1517 
1518  template <typename... ArgTs>
1519  void operator()(ArgTs... args)
1520  {
1521  f(c0, c1, c2, c3, c4, args...);
1522  }
1523  };
1524 #endif //!defined(DOXYGEN_ONLY)
1525 };
1526 
1527 /** @}*/
1528 /** @}*/
1529 
1530 }
1531 
1532 #endif
void dispatch_forever()
Dispatch events without a timeout.
int time_left(int id)
Query how much time is left for delayed event.
void break_dispatch()
Break out of a running event loop.
void dispatch_once()
Dispatch currently queued events only and then terminate.
EventQueue.
Definition: EventQueue.h:62
int call_every(duration ms, F f, ArgTs...args)
Calls an event on the queue periodically.
Event.
Definition: Event.h:38
int chain(EventQueue *target)
Chain an event queue onto another event queue.
bool cancel(UserAllocatedEvent< F, A > *event)
Cancel an in-flight user allocated event.
Definition: EventQueue.h:195
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=nullptr) noexcept
Create a callback class with type inferred from the arguments.
Definition: Callback.h:678
UserAllocatedEvent< F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs...args)
Creates an user allocated event bound to the event queue.
unsigned tick()
Millisecond counter.
Definition: equeue.h:61
bool cancel(int id)
Cancel an in-flight event.
int call_in(duration ms, F f, ArgTs...args)
Calls an event on the queue after a specified delay.
void background(mbed::Callback< void(int)> update)
Background an event queue onto a single-shot timer-interrupt.
void dispatch_for(duration ms)
Dispatch events.
int call(F f, Args...args)
Calls an event on the queue.
Event< void(ArgTs...)> event(R(*func)(BoundArgTs..., ArgTs...), ContextArgTs...context_args)
Creates an event bound to the event queue.
~EventQueue()
Destroy an EventQueue.
EventQueue(unsigned size=(32 *(EQUEUE_EVENT_SIZE-2 *sizeof(void *)+sizeof(mbed::Callback< void()>))), unsigned char *buffer=NULL)
Create an EventQueue.
int time_left(UserAllocatedEvent< F, A > *event)
Query how much time is left for delayed UserAllocatedEvent.
Definition: EventQueue.h:241
Callback class based on template specialization.
Definition: Callback.h:53
#define EVENTS_QUEUE_SIZE
EVENTS_QUEUE_SIZE Default size of buffer for events.
Definition: EventQueue.h:45
void dispatch(int ms=-1)
Dispatch events.
#define MBED_DEPRECATED_SINCE(D, M)
MBED_DEPRECATED("message string") Mark a function declaration as deprecated, if it used then a warnin...
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.