1
This commit is contained in:
1 parent
226a5744b5
commit
4556f327c2
10 files changed
+63
-94
No files matched your search
+17
-24
@@ -291,13 +291,15 @@ static void check_waiters(struct ll_queue* q) {
|
||||
|
||||
struct queue_waiter_handle* h = waiter->handle;
|
||||
if (h) h->internal = NULL;
|
||||
|
||||
|
||||
queue_threshold_callback_fn cb = waiter->callback;
|
||||
void* arg = waiter->callback_arg;
|
||||
u_free(waiter);
|
||||
|
||||
if (h) {
|
||||
|
||||
if (cb) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_LL_QUEUE, "check_waiters: waking head waiter, count=%d<=%d, bytes=%zu<=%zu",
|
||||
q->count, q->threshold_max_packets, q->total_bytes, q->threshold_max_bytes);
|
||||
h->callback(q, h->callback_arg);
|
||||
cb(q, arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,29 +556,18 @@ void queue_set_threshold(struct ll_queue* q, int max_packets, size_t max_bytes)
|
||||
q->threshold_max_bytes = max_bytes;
|
||||
}
|
||||
|
||||
void queue_waiter_handle_init(struct queue_waiter_handle* h,
|
||||
queue_threshold_callback_fn callback, void* arg) {
|
||||
if (!h) return;
|
||||
h->internal = NULL;
|
||||
h->callback = callback;
|
||||
h->callback_arg = arg;
|
||||
}
|
||||
int queue_waiter_wait(struct ll_queue* q, struct queue_waiter_handle* h,
|
||||
queue_threshold_callback_fn callback, void* arg) {
|
||||
if (!q || !h) return -1;
|
||||
|
||||
if (h->internal) queue_waiter_cancel(q, h);
|
||||
|
||||
int queue_waiter_wait(struct ll_queue* q, struct queue_waiter_handle* h) {
|
||||
if (!q || !h) return 1;
|
||||
|
||||
if (h->internal) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_LL_QUEUE, "[%s] queue_waiter_wait: waiter already registered", q->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Проверить условие немедленно
|
||||
if (q->count <= q->threshold_max_packets
|
||||
&& (q->threshold_max_bytes == 0 || q->total_bytes <= q->threshold_max_bytes)) {
|
||||
h->callback(q, h->callback_arg);
|
||||
callback(q, arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct queue_waiter* waiter = u_malloc(sizeof(struct queue_waiter));
|
||||
if (!waiter) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_LL_QUEUE, "[%s] queue_waiter_wait: u_malloc failed", q->name);
|
||||
@@ -584,11 +575,13 @@ int queue_waiter_wait(struct ll_queue* q, struct queue_waiter_handle* h) {
|
||||
}
|
||||
waiter->next = NULL;
|
||||
waiter->handle = h;
|
||||
waiter->callback = callback;
|
||||
waiter->callback_arg = arg;
|
||||
h->internal = waiter;
|
||||
|
||||
|
||||
if (q->waiter_tail) q->waiter_tail->next = waiter; else q->waiter_head = waiter;
|
||||
q->waiter_tail = waiter;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+11
-16
@@ -99,6 +99,8 @@ typedef void (*queue_threshold_callback_fn)(struct ll_queue* q, void* arg);
|
||||
struct queue_waiter {
|
||||
struct queue_waiter* next; ///< Следующий в списке ожидающих
|
||||
struct queue_waiter_handle* handle; ///< Обратная ссылка на публичную структуру
|
||||
queue_threshold_callback_fn callback;
|
||||
void* callback_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -106,15 +108,12 @@ struct queue_waiter {
|
||||
* @brief Публичная управляющая структура (встраивается в структуру вызывающей стороны).
|
||||
*
|
||||
* Вызывающая сторона:
|
||||
* 1. Объявляет поле struct queue_waiter_handle в своей структуре
|
||||
* 2. Вызывает queue_waiter_handle_init() один раз при инициализации
|
||||
* 1. Объявляет поле struct queue_waiter_handle в своей структуре (= {0} или u_calloc)
|
||||
* 3. Вызывает queue_waiter_wait() когда хочет дождаться освобождения очереди
|
||||
* 4. Вызывает queue_waiter_cancel() при деинициализации для отмены ожидания
|
||||
*/
|
||||
struct queue_waiter_handle {
|
||||
struct queue_waiter* internal; ///< NULL = не ждём; иначе — внутренний узел
|
||||
queue_threshold_callback_fn callback;
|
||||
void* callback_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -223,22 +222,18 @@ void queue_resume_callback(struct ll_queue* q);
|
||||
*/
|
||||
void queue_set_threshold(struct ll_queue* q, int max_packets, size_t max_bytes);
|
||||
|
||||
/**
|
||||
* @brief Инициализирует публичную управляющую структуру waiter.
|
||||
* @param h указатель на handle (встраивается в структуру вызывающей стороны)
|
||||
* @param callback функция, вызываемая при достижении порога
|
||||
* @param arg аргумент коллбэка
|
||||
*/
|
||||
void queue_waiter_handle_init(struct queue_waiter_handle* h,
|
||||
queue_threshold_callback_fn callback, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Регистрирует ожидание освобождения очереди до общего порога.
|
||||
* @param q очередь
|
||||
* @param h указатель на инициализированный handle
|
||||
* @return 1 — условие уже выполнено (callback вызван немедленно), 0 — зарегистрирован в списке
|
||||
* @param h указатель на handle (создаётся как `struct queue_waiter_handle h = {0}` или `h.internal = NULL`)
|
||||
* @param callback функция, вызываемая при достижении порога
|
||||
* @param arg аргумент коллбэка
|
||||
* @return 1 — условие уже выполнено (callback вызван немедленно), 0 — зарегистрирован в списке, -1 — ошибка
|
||||
*
|
||||
* Если handle уже ожидает (h->internal != NULL) — старый waiter отменяется и создаётся новый.
|
||||
*/
|
||||
int queue_waiter_wait(struct ll_queue* q, struct queue_waiter_handle* h);
|
||||
int queue_waiter_wait(struct ll_queue* q, struct queue_waiter_handle* h,
|
||||
queue_threshold_callback_fn callback, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Отменяет ожидание (удаляет из списка, если зарегистрирован).
|
||||
|
||||
Reference in new issue
Block a user