Merge pull request #14682 from maribu/event_wait_prio
This commit is contained in:
commit
7b05b85135
@ -96,14 +96,20 @@ event_t *event_get(event_queue_t *queue)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_t *event_wait(event_queue_t *queue)
|
event_t *event_wait_multi(event_queue_t *queues, size_t n_queues)
|
||||||
{
|
{
|
||||||
assert(queue);
|
assert(queues && n_queues);
|
||||||
event_t *result;
|
event_t *result;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
unsigned state = irq_disable();
|
unsigned state = irq_disable();
|
||||||
result = (event_t *)clist_lpop(&queue->event_list);
|
for (size_t i = 0; i < n_queues; i++) {
|
||||||
|
result = container_of(clist_lpop(&queues[i].event_list),
|
||||||
|
event_t, list_node);
|
||||||
|
if (result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
irq_restore(state);
|
irq_restore(state);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
thread_flags_wait_any(THREAD_FLAG_EVENT);
|
thread_flags_wait_any(THREAD_FLAG_EVENT);
|
||||||
@ -152,11 +158,11 @@ event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void event_loop(event_queue_t *queue)
|
void event_loop_multi(event_queue_t *queues, size_t n_queues)
|
||||||
{
|
{
|
||||||
event_t *event;
|
event_t *event;
|
||||||
|
|
||||||
while ((event = event_wait(queue))) {
|
while ((event = event_wait_multi(queues, n_queues))) {
|
||||||
event->handler(event);
|
event->handler(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -215,6 +215,35 @@ void event_cancel(event_queue_t *queue, event_t *event);
|
|||||||
*/
|
*/
|
||||||
event_t *event_get(event_queue_t *queue);
|
event_t *event_get(event_queue_t *queue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get next event from the given event queues, blocking
|
||||||
|
*
|
||||||
|
* This function will block until an event becomes available. If more than one
|
||||||
|
* queue contains an event, the queue with the lowest index is chosen. Thus,
|
||||||
|
* a lower index in the @p queues array translates into a higher priority of
|
||||||
|
* the queue.
|
||||||
|
*
|
||||||
|
* In order to handle an event retrieved using this function,
|
||||||
|
* call event->handler(event).
|
||||||
|
*
|
||||||
|
* @warning There can only be a single waiter on a queue!
|
||||||
|
*
|
||||||
|
* @note This function *can* be suitable for having a single thread
|
||||||
|
* handling both real-time and non-real-time events. However, a real
|
||||||
|
* time event can be delayed for the whole duration a single
|
||||||
|
* non-real-time event takes (in addition to all other sources of
|
||||||
|
* latency). Thus, the slowest to handle non-real-time event must still
|
||||||
|
* execute fast enough to add an amount of latency (on top of other
|
||||||
|
* sources of latency) that is acceptable to the real-time event with
|
||||||
|
* the strictest requirements.
|
||||||
|
*
|
||||||
|
* @param[in] queues Array of event queues to get event from
|
||||||
|
* @param[in] n_queues Number of event queues passed in @p queues
|
||||||
|
*
|
||||||
|
* @returns pointer to next event
|
||||||
|
*/
|
||||||
|
event_t *event_wait_multi(event_queue_t *queues, size_t n_queues);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get next event from event queue, blocking
|
* @brief Get next event from event queue, blocking
|
||||||
*
|
*
|
||||||
@ -223,13 +252,16 @@ event_t *event_get(event_queue_t *queue);
|
|||||||
* In order to handle an event retrieved using this function,
|
* In order to handle an event retrieved using this function,
|
||||||
* call event->handler(event).
|
* call event->handler(event).
|
||||||
*
|
*
|
||||||
* @note There can only be a single waiter on a queue!
|
* @warning There can only be a single waiter on a queue!
|
||||||
*
|
*
|
||||||
* @param[in] queue event queue to get event from
|
* @param[in] queue event queue to get event from
|
||||||
*
|
*
|
||||||
* @returns pointer to next event
|
* @returns pointer to next event
|
||||||
*/
|
*/
|
||||||
event_t *event_wait(event_queue_t *queue);
|
static inline event_t *event_wait(event_queue_t *queue)
|
||||||
|
{
|
||||||
|
return event_wait_multi(queue, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MODULE_XTIMER) || defined(DOXYGEN)
|
#if defined(MODULE_XTIMER) || defined(DOXYGEN)
|
||||||
/**
|
/**
|
||||||
@ -255,6 +287,29 @@ event_t *event_wait_timeout(event_queue_t *queue, uint32_t timeout);
|
|||||||
event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout);
|
event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple event loop with multiple queues
|
||||||
|
*
|
||||||
|
* This function will forever sit in a loop, waiting for events to be queued
|
||||||
|
* and executing their handlers. If more than one queue contains an event, the
|
||||||
|
* queue with the lowest index is chosen. Thus, a lower index in the @p queues
|
||||||
|
* array translates into a higher priority of the queue.
|
||||||
|
*
|
||||||
|
* It is pretty much defined as:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* while ((event = event_wait_multi(queues, n_queues))) {
|
||||||
|
* event->handler(event);
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* @see event_wait_multi
|
||||||
|
*
|
||||||
|
* @param[in] queues Event queues to process
|
||||||
|
* @param[in] n_queues Number of queues passed with @p queues
|
||||||
|
*/
|
||||||
|
void event_loop_multi(event_queue_t *queues, size_t n_queues);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple event loop
|
* @brief Simple event loop
|
||||||
*
|
*
|
||||||
@ -271,7 +326,10 @@ event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout);
|
|||||||
*
|
*
|
||||||
* @param[in] queue event queue to process
|
* @param[in] queue event queue to process
|
||||||
*/
|
*/
|
||||||
void event_loop(event_queue_t *queue);
|
static inline void event_loop(event_queue_t *queue)
|
||||||
|
{
|
||||||
|
event_loop_multi(queue, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,9 @@
|
|||||||
#include "event/timeout.h"
|
#include "event/timeout.h"
|
||||||
#include "event/callback.h"
|
#include "event/callback.h"
|
||||||
|
|
||||||
#define STACKSIZE THREAD_STACKSIZE_DEFAULT
|
#define STACKSIZE THREAD_STACKSIZE_DEFAULT
|
||||||
#define PRIO (THREAD_PRIORITY_MAIN - 1)
|
#define PRIO (THREAD_PRIORITY_MAIN - 1)
|
||||||
|
#define DELAYED_QUEUES_NUMOF 2
|
||||||
|
|
||||||
static char stack[STACKSIZE];
|
static char stack[STACKSIZE];
|
||||||
|
|
||||||
@ -42,16 +43,18 @@ static void timed_callback(void *arg);
|
|||||||
static void forbidden_callback(void *arg);
|
static void forbidden_callback(void *arg);
|
||||||
static void delayed_callback1(event_t *arg);
|
static void delayed_callback1(event_t *arg);
|
||||||
static void delayed_callback2(event_t *arg);
|
static void delayed_callback2(event_t *arg);
|
||||||
|
static void delayed_callback3(event_t *arg);
|
||||||
|
|
||||||
static event_t event = { .handler = callback };
|
static event_t event = { .handler = callback };
|
||||||
static event_t event2 = { .handler = callback };
|
static event_t event2 = { .handler = callback };
|
||||||
static event_t delayed_event1 = { .handler = delayed_callback1 };
|
static event_t delayed_event1 = { .handler = delayed_callback1 };
|
||||||
static event_t delayed_event2 = { .handler = delayed_callback2 };
|
static event_t delayed_event2 = { .handler = delayed_callback2 };
|
||||||
|
static event_t delayed_event3 = { .handler = delayed_callback3 };
|
||||||
|
|
||||||
static void callback(event_t *arg)
|
static void callback(event_t *arg)
|
||||||
{
|
{
|
||||||
order++;
|
order++;
|
||||||
expect(order == 3);
|
expect(order == 4);
|
||||||
expect(arg == &event);
|
expect(arg == &event);
|
||||||
printf("triggered 0x%08x\n", (unsigned)arg);
|
printf("triggered 0x%08x\n", (unsigned)arg);
|
||||||
}
|
}
|
||||||
@ -68,7 +71,7 @@ static event_callback_t noevent_callback = EVENT_CALLBACK_INIT(forbidden_callbac
|
|||||||
static void custom_callback(event_t *event)
|
static void custom_callback(event_t *event)
|
||||||
{
|
{
|
||||||
order++;
|
order++;
|
||||||
expect(order == 4);
|
expect(order == 5);
|
||||||
expect(event == (event_t *)&custom_event);
|
expect(event == (event_t *)&custom_event);
|
||||||
custom_event_t *custom_event = (custom_event_t *)event;
|
custom_event_t *custom_event = (custom_event_t *)event;
|
||||||
printf("triggered custom event with text: \"%s\"\n", custom_event->text);
|
printf("triggered custom event with text: \"%s\"\n", custom_event->text);
|
||||||
@ -77,7 +80,7 @@ static void custom_callback(event_t *event)
|
|||||||
static void timed_callback(void *arg)
|
static void timed_callback(void *arg)
|
||||||
{
|
{
|
||||||
order++;
|
order++;
|
||||||
expect(order == 5);
|
expect(order == 6);
|
||||||
expect(arg == event_callback.arg);
|
expect(arg == event_callback.arg);
|
||||||
uint32_t now = xtimer_now_usec();
|
uint32_t now = xtimer_now_usec();
|
||||||
expect((now - before >= 100000LU));
|
expect((now - before >= 100000LU));
|
||||||
@ -99,7 +102,7 @@ static void forbidden_callback(void *arg)
|
|||||||
static void delayed_callback1(event_t *arg)
|
static void delayed_callback1(event_t *arg)
|
||||||
{
|
{
|
||||||
order++;
|
order++;
|
||||||
expect(order == 1);
|
expect(order == 2);
|
||||||
expect(arg == &delayed_event1);
|
expect(arg == &delayed_event1);
|
||||||
printf("triggered delayed event %p\n", (void *)arg);
|
printf("triggered delayed event %p\n", (void *)arg);
|
||||||
}
|
}
|
||||||
@ -107,19 +110,29 @@ static void delayed_callback1(event_t *arg)
|
|||||||
static void delayed_callback2(event_t *arg)
|
static void delayed_callback2(event_t *arg)
|
||||||
{
|
{
|
||||||
order++;
|
order++;
|
||||||
expect(order == 2);
|
expect(order == 3);
|
||||||
expect(arg == &delayed_event2);
|
expect(arg == &delayed_event2);
|
||||||
printf("triggered delayed event %p\n", (void *)arg);
|
printf("triggered delayed event %p\n", (void *)arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void delayed_callback3(event_t *arg)
|
||||||
|
{
|
||||||
|
order++;
|
||||||
|
expect(order == 1);
|
||||||
|
expect(arg == &delayed_event3);
|
||||||
|
printf("triggered delayed event %p\n", (void *)arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void *claiming_thread(void *arg)
|
static void *claiming_thread(void *arg)
|
||||||
{
|
{
|
||||||
event_queue_t *dq = (event_queue_t *)arg;
|
event_queue_t *dqs = arg;
|
||||||
|
|
||||||
printf("claiming event queue %p\n", (void *)dq);
|
printf("claiming event queues %p\n", (void *)dqs);
|
||||||
event_queue_claim(dq);
|
for (size_t i = 0; i < DELAYED_QUEUES_NUMOF; i++) {
|
||||||
printf("launching event queue %p\n", (void *)dq);
|
event_queue_claim(&dqs[i]);
|
||||||
event_loop(dq);
|
}
|
||||||
|
printf("launching event queue for queues %p\n", (void *)dqs);
|
||||||
|
event_loop_multi(dqs, DELAYED_QUEUES_NUMOF);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -129,17 +142,22 @@ int main(void)
|
|||||||
puts("[START] event test application.\n");
|
puts("[START] event test application.\n");
|
||||||
|
|
||||||
/* test creation of delayed claiming of a detached event queue */
|
/* test creation of delayed claiming of a detached event queue */
|
||||||
event_queue_t dq = EVENT_QUEUE_INIT_DETACHED;
|
event_queue_t dqs[DELAYED_QUEUES_NUMOF] = {
|
||||||
printf("initializing detached event queue %p\n", (void *)&dq);
|
EVENT_QUEUE_INIT_DETACHED, EVENT_QUEUE_INIT_DETACHED
|
||||||
event_queue_init_detached(&dq);
|
};
|
||||||
|
printf("initializing detached event queues %p\n", (void *)dqs);
|
||||||
|
event_queue_init_detached(&dqs[0]);
|
||||||
|
event_queue_init_detached(&dqs[1]);
|
||||||
|
|
||||||
printf("posting %p\n", (void *)&delayed_event1);
|
printf("posting %p to delayed queue at index 1\n", (void *)&delayed_event1);
|
||||||
event_post(&dq, &delayed_event1);
|
event_post(&dqs[1], &delayed_event1);
|
||||||
printf("posting %p\n", (void *)&delayed_event2);
|
printf("posting %p to delayed queue at index 1\n", (void *)&delayed_event2);
|
||||||
event_post(&dq, &delayed_event2);
|
event_post(&dqs[1], &delayed_event2);
|
||||||
|
printf("posting %p to delayed queue at index 0\n", (void *)&delayed_event3);
|
||||||
|
event_post(&dqs[0], &delayed_event3);
|
||||||
|
|
||||||
printf("running thread that will claim event queue %p\n", (void *)&dq);
|
printf("running thread that will claim event queues %p\n", (void *)&dqs);
|
||||||
thread_create(stack, sizeof(stack), PRIO, 0, claiming_thread, &dq, "ct");
|
thread_create(stack, sizeof(stack), PRIO, 0, claiming_thread, dqs, "ct");
|
||||||
|
|
||||||
/* test posting different kind of events in order to a statically
|
/* test posting different kind of events in order to a statically
|
||||||
* initialized queue */
|
* initialized queue */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user