mirror of https://github.com/ARMmbed/mbed-os.git
UserAllocatedEvent implementation
UserAllocatedEvent provides mechanism for event posting and dispatching without utilization of queue internal memory. UserAllocatedEvent embeds all underlying event data and doesn't require any memory allocation while posting and dispatching. All of these makes it cannot fail due to memory exhaustion while posting.pull/11342/head
parent
e7e5cd2aa4
commit
19e33ba44b
|
@ -45,6 +45,8 @@ namespace events {
|
|||
// Predeclared classes
|
||||
template <typename F>
|
||||
class Event;
|
||||
template <typename F, typename A>
|
||||
class UserAllocatedEvent;
|
||||
|
||||
/**
|
||||
* \defgroup events_EventQueue EventQueue class
|
||||
|
@ -60,10 +62,17 @@ public:
|
|||
/** Create an EventQueue
|
||||
*
|
||||
* Create an event queue. The event queue either allocates a buffer of
|
||||
* the specified size with malloc or uses the user provided buffer.
|
||||
* the specified size with malloc or uses the user provided buffer or
|
||||
* uses 1B dummy buffer if 0 size passed.
|
||||
*
|
||||
* 0 size queue is a special purpose queue to dispatch static events
|
||||
* only (see UserAllocatedEvent). Such a queue gives the guarantee
|
||||
* that no dynamic memory allocation will take place while queue
|
||||
* creation and events posting & dispatching.
|
||||
*
|
||||
* @param size Size of buffer to use for events in bytes
|
||||
* (default to EVENTS_QUEUE_SIZE)
|
||||
* If 0 provided then 1B dummy buffer is used
|
||||
* @param buffer Pointer to buffer to use for events
|
||||
* (default to NULL)
|
||||
*/
|
||||
|
@ -139,6 +148,34 @@ public:
|
|||
*/
|
||||
bool cancel(int id);
|
||||
|
||||
/** Cancel an in-flight user allocated event
|
||||
*
|
||||
* Attempts to cancel an UserAllocatedEvent referenced by its address
|
||||
* It is safe to call cancel after an event has already been dispatched.
|
||||
*
|
||||
* Event must be valid i.e. event must have not finished executing
|
||||
* and must have been bound to this queue.
|
||||
*
|
||||
* The cancel function is IRQ safe.
|
||||
*
|
||||
* If called while the event queue's dispatch loop is active in another thread,
|
||||
* the cancel function does not guarantee that the event will not execute after it
|
||||
* returns, as the event may have already begun executing. A call made from
|
||||
* the same thread as the dispatch loop will always succeed with a valid id.
|
||||
*
|
||||
* @param event Address of the event
|
||||
* @return true if event was successfully cancelled
|
||||
* false if event was not cancelled (invalid queue or executing already begun)
|
||||
*/
|
||||
template<typename... Args>
|
||||
bool cancel(UserAllocatedEvent<Args...> *event)
|
||||
{
|
||||
if (event->_equeue != &_equeue) {
|
||||
return false;
|
||||
}
|
||||
return equeue_cancel_user_allocated(&_equeue, event);
|
||||
}
|
||||
|
||||
/** Query how much time is left for delayed event
|
||||
*
|
||||
* If the event is delayed, this function can be used to query how much time
|
||||
|
@ -158,6 +195,33 @@ public:
|
|||
*/
|
||||
int time_left(int id);
|
||||
|
||||
/** Query how much time is left for delayed UserAllocatedEvent
|
||||
*
|
||||
* If the event is delayed, this function can be used to query how much time
|
||||
* is left until the event is due to be dispatched.
|
||||
*
|
||||
* Event must be valid i.e. event must have not finished executing
|
||||
* and must have been bound to this queue.
|
||||
*
|
||||
* This function is IRQ safe.
|
||||
*
|
||||
* @param event Address of the event
|
||||
*
|
||||
* @return Remaining time in milliseconds or
|
||||
* 0 if event is already due to be dispatched or
|
||||
* is currently executing.
|
||||
* Undefined if id is invalid.
|
||||
*
|
||||
*/
|
||||
template<typename... Args>
|
||||
int time_left(UserAllocatedEvent<Args...> *event)
|
||||
{
|
||||
if (event && event->_equeue != &_equeue) {
|
||||
return -1;
|
||||
}
|
||||
return equeue_timeleft_user_allocated(&_equeue, &event->_e);
|
||||
}
|
||||
|
||||
/** Background an event queue onto a single-shot timer-interrupt
|
||||
*
|
||||
* When updated, the event queue will call the provided update function
|
||||
|
@ -597,6 +661,53 @@ public:
|
|||
template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
|
||||
Event<void(Args...)> event(mbed::Callback<R(BoundArgs..., Args...)> cb, ContextArgs ...context_args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
*
|
||||
* Constructs an user allocated event bound to the specified event queue.
|
||||
* The specified callback acts as the target for the event and is executed
|
||||
* in the context of the event queue's dispatch loop once posted.
|
||||
*
|
||||
* @code
|
||||
* #include "mbed.h"
|
||||
*
|
||||
* void handler(int data) { ... }
|
||||
*
|
||||
* class Device {
|
||||
* public:
|
||||
* void handler(int data) { ... }
|
||||
* };
|
||||
*
|
||||
* Device dev;
|
||||
*
|
||||
* // queue with not internal storage for dynamic events
|
||||
* // accepts only user allocated events
|
||||
* static EventQueue queue(0);
|
||||
* // Create events
|
||||
* static auto e1 = make_user_allocated_event(&dev, Device::handler, 2);
|
||||
* static auto e2 = queue.make_user_allocated_event(handler, 3);
|
||||
*
|
||||
* int main()
|
||||
* {
|
||||
* e1.call_on(&queue);
|
||||
* e2.call();
|
||||
*
|
||||
* queue.dispatch(1);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param f Function to execute when the event is dispatched
|
||||
* @return Event that will dispatch on the specific queue
|
||||
*/
|
||||
template <typename F, typename... ArgTs>
|
||||
UserAllocatedEvent<F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs... args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
* @see EventQueue::make_user_allocated_event
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/** Calls an event on the queue
|
||||
|
@ -1068,12 +1179,50 @@ public:
|
|||
*/
|
||||
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>
|
||||
Event<void(ArgTs...)> event(mbed::Callback<R(B0, B1, B2, B3, B4, ArgTs...)> cb, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
*
|
||||
* Constructs an user allocated event bound to the specified event queue.
|
||||
* The specified callback acts as the target for the event and is executed
|
||||
* in the context of the event queue's dispatch loop once posted.
|
||||
*
|
||||
* @param f Function to execute when the event is dispatched
|
||||
* @return Event that will dispatch on the specific queue
|
||||
*/
|
||||
template <typename F, typename... ArgTs>
|
||||
UserAllocatedEvent<F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs... args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
* @see EventQueue::make_user_allocated_event
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
* @see EventQueue::make_user_allocated_event
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const T *obj, R(T::*method)(ArgTs... args) const, ArgTs... args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
* @see EventQueue::make_user_allocated_event
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(volatile T *obj, R(T::*method)(ArgTs... args) volatile, ArgTs... args);
|
||||
|
||||
/** Creates an user allocated event bound to the event queue
|
||||
* @see EventQueue::make_user_allocated_event
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const volatile T *obj, R(T::*method)(ArgTs... args) const volatile, ArgTs... args);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
template <typename F>
|
||||
friend class Event;
|
||||
template <typename F, typename A>
|
||||
friend class UserAllocatedEvent;
|
||||
struct equeue _equeue;
|
||||
mbed::Callback<void(int)> _update;
|
||||
|
||||
|
@ -1098,7 +1247,7 @@ protected:
|
|||
struct context<F> {
|
||||
F f;
|
||||
|
||||
context(F f)
|
||||
constexpr context(F f)
|
||||
: f(f) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
@ -1113,7 +1262,7 @@ protected:
|
|||
F f;
|
||||
C0 c0;
|
||||
|
||||
context(F f, C0 c0)
|
||||
constexpr context(F f, C0 c0)
|
||||
: f(f), c0(c0) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
@ -1129,7 +1278,7 @@ protected:
|
|||
C0 c0;
|
||||
C1 c1;
|
||||
|
||||
context(F f, C0 c0, C1 c1)
|
||||
constexpr context(F f, C0 c0, C1 c1)
|
||||
: f(f), c0(c0), c1(c1) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
@ -1146,7 +1295,7 @@ protected:
|
|||
C1 c1;
|
||||
C2 c2;
|
||||
|
||||
context(F f, C0 c0, C1 c1, C2 c2)
|
||||
constexpr context(F f, C0 c0, C1 c1, C2 c2)
|
||||
: f(f), c0(c0), c1(c1), c2(c2) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
@ -1164,7 +1313,7 @@ protected:
|
|||
C2 c2;
|
||||
C3 c3;
|
||||
|
||||
context(F f, C0 c0, C1 c1, C2 c2, C3 c3)
|
||||
constexpr context(F f, C0 c0, C1 c1, C2 c2, C3 c3)
|
||||
: f(f), c0(c0), c1(c1), c2(c2), c3(c3) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
@ -1183,7 +1332,7 @@ protected:
|
|||
C3 c3;
|
||||
C4 c4;
|
||||
|
||||
context(F f, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4)
|
||||
constexpr context(F f, C0 c0, C1 c1, C2 c2, C3 c3, C4 c4)
|
||||
: f(f), c0(c0), c1(c1), c2(c2), c3(c3), c4(c4) {}
|
||||
|
||||
template <typename... ArgTs>
|
||||
|
|
|
@ -0,0 +1,460 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef USER_ALLOCATED_EVENT_H
|
||||
#define USER_ALLOCATED_EVENT_H
|
||||
|
||||
#include "events/EventQueue.h"
|
||||
#include "platform/mbed_assert.h"
|
||||
#include "platform/mbed_atomic.h"
|
||||
|
||||
namespace events {
|
||||
/**
|
||||
* \addtogroup events-public-api Events
|
||||
* \ingroup mbed-os-public
|
||||
* @{
|
||||
*/
|
||||
template <typename F, typename A>
|
||||
class UserAllocatedEvent;
|
||||
|
||||
/**
|
||||
* \defgroup events_Event UserAllocatedEvent class
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** UserAllocatedEvent
|
||||
*
|
||||
* Representation of an static event for fine-grain dispatch control.
|
||||
*
|
||||
* UserAllocatedEvent provides mechanism for event posting and dispatching
|
||||
* without utilization of queue internal memory. It embeds all underlying
|
||||
* event data and doesn't require any memory allocation while posting and dispatching.
|
||||
* All of these makes it cannot fail due to memory exhaustion while posting
|
||||
*
|
||||
* Usage:
|
||||
* @code
|
||||
* #include "mbed.h"
|
||||
*
|
||||
* void handler(int data) { ... }
|
||||
*
|
||||
* class Device {
|
||||
* public:
|
||||
* void handler(int data) { ... }
|
||||
* };
|
||||
*
|
||||
* Device dev;
|
||||
*
|
||||
* // queue with not internal storage for dynamic events
|
||||
* // accepts only user allocated events
|
||||
* static EventQueue queue(0);
|
||||
* // Create events
|
||||
* static auto e1 = make_user_allocated_event(&dev, Device::handler, 2);
|
||||
* static auto e2 = queue.make_user_allocated_event(handler, 3);
|
||||
*
|
||||
* int main()
|
||||
* {
|
||||
* e1.call_on(&queue);
|
||||
* e2.call();
|
||||
*
|
||||
* queue.dispatch(1);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
template <typename F, typename... ArgTs>
|
||||
class UserAllocatedEvent<F, void(ArgTs...)> {
|
||||
public:
|
||||
typedef EventQueue::context<F, ArgTs...> C;
|
||||
|
||||
/** Create an event
|
||||
*
|
||||
* Constructs an event. The specified callback acts as the target
|
||||
* for the event and is executed in the context of the
|
||||
* event queue's dispatch loop once posted.
|
||||
*
|
||||
* @param f Function to execute when the event is dispatched
|
||||
* @param args Arguments to bind to the callback
|
||||
*/
|
||||
constexpr UserAllocatedEvent(F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _equeue(), _post_ref()
|
||||
{
|
||||
}
|
||||
|
||||
/** Create an event
|
||||
*
|
||||
* Constructs an event. The specified callback acts as the target
|
||||
* for the event and is executed in the context of the
|
||||
* event queue's dispatch loop once posted.
|
||||
*
|
||||
* @param queue Event queue to dispatch on
|
||||
* @param f Function to execute when the event is dispatched
|
||||
* @param args Arguments to bind to the callback
|
||||
*/
|
||||
constexpr UserAllocatedEvent(EventQueue *queue, F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _equeue(&queue->_equeue), _post_ref()
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor for events
|
||||
*/
|
||||
#if !defined(NDEBUG)
|
||||
// Remove the user provided destructor in release to allow constexpr optimization
|
||||
// constexpr requires destructor to be trivial and only default one is treated as trivial
|
||||
~UserAllocatedEvent()
|
||||
{
|
||||
MBED_ASSERT(!_post_ref);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Posts an event onto the underlying event queue, returning void
|
||||
*
|
||||
* The event is posted to the underlying queue and is executed in the
|
||||
* context of the event queue's dispatch loop.
|
||||
*
|
||||
* This call cannot fail due queue memory exhaustion
|
||||
* because it doesn't allocate any memory
|
||||
*
|
||||
* The post function is IRQ safe and can act as a mechanism for moving
|
||||
* events out of IRQ contexts.
|
||||
*
|
||||
*/
|
||||
void call()
|
||||
{
|
||||
MBED_ASSERT(!_post_ref);
|
||||
MBED_ASSERT(_equeue);
|
||||
MBED_UNUSED bool status = post();
|
||||
MBED_ASSERT(status);
|
||||
}
|
||||
|
||||
/** Posts an event onto the event queue passed as argument, returning void
|
||||
*
|
||||
* The event is posted to the event queue passed as argument
|
||||
* and is executed in the context of the event queue's dispatch loop.
|
||||
*
|
||||
* This call cannot fail due queue memory exhaustion
|
||||
* because it doesn't allocate any memory
|
||||
*
|
||||
* The post function is IRQ safe and can act as a mechanism for moving
|
||||
* events out of IRQ contexts.
|
||||
*
|
||||
* @param queue Event queue to dispatch on. Will replace earlier bound EventQueue.
|
||||
*
|
||||
*/
|
||||
void call_on(EventQueue *queue)
|
||||
{
|
||||
MBED_ASSERT(!_post_ref);
|
||||
MBED_UNUSED bool status = post_on(queue);
|
||||
MBED_ASSERT(status);
|
||||
}
|
||||
|
||||
/** Posts an event onto the underlying event queue
|
||||
*
|
||||
* The event is posted to the event queue passed as argument
|
||||
* and is executed in the context of the event queue's dispatch loop.
|
||||
*
|
||||
* This call cannot fail due queue memory exhaustion
|
||||
* because it doesn't allocate any memory
|
||||
*
|
||||
* @return False if the event was already posted
|
||||
* true otherwise
|
||||
*
|
||||
*/
|
||||
bool try_call()
|
||||
{
|
||||
return post();
|
||||
}
|
||||
|
||||
/** Posts an event onto the event queue passed as argument,
|
||||
*
|
||||
* The event is posted to the underlying queue and is executed in the
|
||||
* context of the event queue's dispatch loop.
|
||||
*
|
||||
* This call cannot fail due queue memory exhaustion
|
||||
* because it doesn't allocate any memory
|
||||
*
|
||||
* @param queue Event queue to dispatch on. Will replace earlier bound EventQueue.
|
||||
* @return False if the event was already posted
|
||||
* true otherwise
|
||||
*
|
||||
*/
|
||||
bool try_call_on(EventQueue *queue)
|
||||
{
|
||||
return post_on(queue);
|
||||
}
|
||||
|
||||
/** Posts an event onto the underlying event queue, returning void
|
||||
*
|
||||
* The event is posted to the underlying queue and is executed in the
|
||||
* context of the event queue's dispatch loop.
|
||||
*
|
||||
* This call cannot fail due queue memory exhaustion
|
||||
* because it doesn't allocate any memory
|
||||
*
|
||||
* The post function is IRQ safe and can act as a mechanism for moving
|
||||
* events out of IRQ contexts.
|
||||
*
|
||||
*/
|
||||
void operator()()
|
||||
{
|
||||
return call();
|
||||
}
|
||||
|
||||
/** Configure the delay of an event
|
||||
*
|
||||
* @param delay Millisecond delay before dispatching the event
|
||||
*/
|
||||
void delay(int delay)
|
||||
{
|
||||
equeue_event_delay(&_e + 1, delay);
|
||||
}
|
||||
|
||||
/** Configure the period of an event
|
||||
*
|
||||
* @param period Millisecond period for repeatedly dispatching an event
|
||||
*/
|
||||
void period(int period)
|
||||
{
|
||||
equeue_event_period(&_e + 1, period);
|
||||
}
|
||||
|
||||
/** Cancels posted event
|
||||
*
|
||||
* Attempts to cancel posted event. It is safe to call
|
||||
* cancel after an event has already been dispatched.
|
||||
*
|
||||
* The cancel function is IRQ safe.
|
||||
*
|
||||
* If called while the event queue's dispatch loop is active, the cancel
|
||||
* function does not guarantee that the event will not execute after it
|
||||
* returns, as the event may have already begun executing.
|
||||
*
|
||||
* @return true if event was successfully cancelled
|
||||
*/
|
||||
bool cancel()
|
||||
{
|
||||
return equeue_cancel_user_allocated(_equeue, &_e);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
friend class EventQueue;
|
||||
struct equeue_event _e;
|
||||
C _c;
|
||||
struct equeue *_equeue;
|
||||
uint8_t _post_ref;
|
||||
|
||||
bool post()
|
||||
{
|
||||
if (_post_ref) {
|
||||
return false;
|
||||
}
|
||||
core_util_atomic_incr_u8(&_post_ref, 1);
|
||||
equeue_post_user_allocated(_equeue, &EventQueue::function_call<C>, &_e);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool post_on(EventQueue *queue)
|
||||
{
|
||||
if (_post_ref) {
|
||||
return false;
|
||||
}
|
||||
_equeue = &(queue->_equeue);
|
||||
core_util_atomic_incr_u8(&_post_ref, 1);
|
||||
equeue_post_user_allocated(_equeue, &EventQueue::function_call<C>, &_e);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void event_dtor(void *p)
|
||||
{
|
||||
UserAllocatedEvent<F, void(ArgTs...)> *instance = (UserAllocatedEvent<F, void(ArgTs...)> *)(((equeue_event *)p) - 1);
|
||||
core_util_atomic_decr_u8(&instance->_post_ref, 1);
|
||||
MBED_ASSERT(!instance->_post_ref);
|
||||
}
|
||||
|
||||
constexpr static equeue_event get_default_equeue_event()
|
||||
{
|
||||
return equeue_event{ 0, 0, 0, NULL, NULL, NULL, 0, -1, &UserAllocatedEvent::event_dtor, NULL };
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(T *obj, R(T::*method)(ArgTs...), ArgTs... args) :
|
||||
UserAllocatedEvent(mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(EventQueue *q, T *obj, R(T::*method)(ArgTs...), ArgTs... args) :
|
||||
UserAllocatedEvent(q, mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args) :
|
||||
UserAllocatedEvent(mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(EventQueue *q, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args) :
|
||||
UserAllocatedEvent(q, mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args) :
|
||||
UserAllocatedEvent(mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(EventQueue *q, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args) :
|
||||
UserAllocatedEvent(q, mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args) :
|
||||
UserAllocatedEvent(mbed::callback(obj, method), args...) { }
|
||||
|
||||
/** Create an event
|
||||
* @see UserAllocatedEvent::UserAllocatedEvent
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
constexpr UserAllocatedEvent(EventQueue *q, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args) :
|
||||
UserAllocatedEvent(q, mbed::callback(obj, method), args...) { }
|
||||
};
|
||||
|
||||
// Convenience functions declared here to avoid cyclic
|
||||
// dependency between Event and EventQueue
|
||||
template <typename F, typename... ArgTs>
|
||||
UserAllocatedEvent<F, void(ArgTs...)> EventQueue::make_user_allocated_event(F f, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<F, void(ArgTs...)>(this, f, args...);
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> EventQueue::make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(this, mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> EventQueue::make_user_allocated_event(const T *obj, R(T::*method)(ArgTs... args) const, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(this, mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> EventQueue::make_user_allocated_event(volatile T *obj, R(T::*method)(ArgTs... args) volatile, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(this, mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> EventQueue::make_user_allocated_event(const volatile T *obj, R(T::*method)(ArgTs... args) const volatile, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(this, mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
|
||||
/** Creates a UserAllocatedEvent object, deducing the target type from the types of arguments
|
||||
*
|
||||
* UserAllocatedEvent doesn't utilize EventQueue internal memory,
|
||||
* therefore it can be posted on the queue without being afraid
|
||||
* of post fail due to queue memory exhaustion
|
||||
*
|
||||
* @return UserAllocatedEvent object instance
|
||||
*
|
||||
*/
|
||||
template <typename F, typename... ArgTs>
|
||||
constexpr UserAllocatedEvent<F, void(ArgTs...)> make_user_allocated_event(F f, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<F, void(ArgTs...)>(f, args...);
|
||||
}
|
||||
|
||||
/** Creates a UserAllocatedEvent object, deducing the target type from the types of arguments
|
||||
*
|
||||
* UserAllocatedEvent doesn't utilize EventQueue internal memory,
|
||||
* therefore it can be posted on the queue without being afraid
|
||||
* of post fail due to queue memory exhaustion
|
||||
*
|
||||
* @return UserAllocatedEvent object instance
|
||||
*
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
constexpr UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(T *obj, R(T::*method)(ArgTs... args), ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
/** Creates a UserAllocatedEvent object, deducing the target type from the types of arguments
|
||||
*
|
||||
* UserAllocatedEvent doesn't utilize EventQueue internal memory,
|
||||
* therefore it can be posted on the queue without being afraid
|
||||
* of post fail due to queue memory exhaustion
|
||||
*
|
||||
* @return UserAllocatedEvent object instance
|
||||
*
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
constexpr UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const T *obj, R(T::*method)(ArgTs... args) const, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
/** Creates a UserAllocatedEvent object, deducing the target type from the types of arguments
|
||||
*
|
||||
* UserAllocatedEvent doesn't utilize EventQueue internal memory,
|
||||
* therefore it can be posted on the queue without being afraid
|
||||
* of post fail due to queue memory exhaustion
|
||||
*
|
||||
* @return UserAllocatedEvent object instance
|
||||
*
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
constexpr UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(volatile T *obj, R(T::*method)(ArgTs... args) volatile, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
/** Creates a UserAllocatedEvent object, deducing the target type from the types of arguments
|
||||
*
|
||||
* UserAllocatedEvent doesn't utilize EventQueue internal memory,
|
||||
* therefore it can be posted on the queue without being afraid
|
||||
* of post fail due to queue memory exhaustion
|
||||
*
|
||||
* @return UserAllocatedEvent object instance
|
||||
*
|
||||
*/
|
||||
template <typename T, typename R, typename... ArgTs>
|
||||
constexpr UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)> make_user_allocated_event(const volatile T *obj, R(T::*method)(ArgTs... args) const volatile, ArgTs... args)
|
||||
{
|
||||
return UserAllocatedEvent<mbed::Callback<void(ArgTs...)>, void(ArgTs...)>(mbed::callback(obj, method), args...);
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
|
||||
/** @}*/
|
||||
}
|
||||
#endif
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "events/EventQueue.h"
|
||||
#include "events/Event.h"
|
||||
#include "events/UserAllocatedEvent.h"
|
||||
|
||||
#include "events/mbed_shared_queues.h"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* events
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
* Copyright (c) 2016-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -23,10 +23,16 @@ namespace events {
|
|||
|
||||
EventQueue::EventQueue(unsigned event_size, unsigned char *event_pointer)
|
||||
{
|
||||
if (!event_pointer) {
|
||||
equeue_create(&_equeue, event_size);
|
||||
if (event_size == 0) {
|
||||
// As static queue (EventQueue(0)) won't perform any access to its dummy buffer
|
||||
// set 1B dummy buffer as pointer to itself
|
||||
equeue_create_inplace(&_equeue, 1, this);
|
||||
} else {
|
||||
equeue_create_inplace(&_equeue, event_size, event_pointer);
|
||||
if (!event_pointer) {
|
||||
equeue_create(&_equeue, event_size);
|
||||
} else {
|
||||
equeue_create_inplace(&_equeue, event_size, event_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue