mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
49 lines
1.3 KiB
C
49 lines
1.3 KiB
C
|
/*
|
||
|
* BIRD -- Deferring calls to the end of the task
|
||
|
*
|
||
|
* (c) 2024 Maria Matejka <mq@jmq.cz>
|
||
|
*
|
||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* There are cases when we need to just run something multiple times after the
|
||
|
* current task ends, mostly for cleanup reasons, and it doesn't need the
|
||
|
* full-blown event list overhead. Therefore, one just can use this tool
|
||
|
* instead. */
|
||
|
|
||
|
#include "lib/birdlib.h"
|
||
|
#include "lib/event.h"
|
||
|
#include "lib/resource.h"
|
||
|
#include "lib/io-loop.h"
|
||
|
|
||
|
struct deferred_call {
|
||
|
struct deferred_call *next;
|
||
|
void (*hook)(struct deferred_call *);
|
||
|
};
|
||
|
|
||
|
struct deferred {
|
||
|
event e;
|
||
|
linpool *lp;
|
||
|
struct deferred_call *first, **last;
|
||
|
};
|
||
|
|
||
|
extern _Thread_local struct deferred local_deferred;
|
||
|
void defer_init(linpool *lp);
|
||
|
|
||
|
static inline void defer_call(struct deferred_call *call, size_t actual_size) {
|
||
|
/* Reallocate the call to the appropriate linpool */
|
||
|
ASSERT_DIE(actual_size < 128);
|
||
|
struct deferred_call *a = lp_alloc(local_deferred.lp, actual_size);
|
||
|
memcpy(a, call, actual_size);
|
||
|
|
||
|
/* If first, send the actual event to the local thread */
|
||
|
if (local_deferred.last == &local_deferred.first)
|
||
|
ev_send_this_thread(&local_deferred.e);
|
||
|
|
||
|
/* Add to list */
|
||
|
a->next = NULL;
|
||
|
*local_deferred.last = a;
|
||
|
local_deferred.last = &a->next;
|
||
|
}
|