feat: send_q backpressure + ll_queue on_get callback + consumer_ack flow control
etcp_router: ROUTER_MAX_SEND_Q_PACKETS=256, router_enqueue_send returns error when send_q full, etcp_route_send propagates -1 on backpressure. ll_queue: queue_set_on_get — deferred callback after each queue_data_get. Replaces manual consumer_ack polling with queue-driven notification. tcp_proxy_server: consumer_ack=1, write_on_get_cb triggers ACK on each write_queue dequeue. Full backpressure chain: write_queue full → no dequeue → no ACK → sender stops → all queues pause write_queue drains → dequeue → on_get → ACK → sender resumes
This commit is contained in:
1 parent
a0da29f1eb
commit
bbf39c091d
5 files changed
+69
-10
No files matched your search
@@ -47,6 +47,7 @@ static inline void queue_check_thread(struct ll_queue* q) {
|
||||
static void queue_resume_timeout_cb(void* arg);
|
||||
static void check_waiters(struct ll_queue* q);
|
||||
static void empty_trampoline(void* arg);
|
||||
static void on_get_trampoline(void* arg);
|
||||
|
||||
static void empty_trampoline(void* arg) {
|
||||
struct ll_queue* q = (struct ll_queue*)arg;
|
||||
@@ -58,6 +59,11 @@ static void empty_trampoline(void* arg) {
|
||||
if (q->count == 0 && cb) cb(q, cb_arg);
|
||||
}
|
||||
|
||||
static void on_get_trampoline(void* arg) {
|
||||
struct ll_queue* q = (struct ll_queue*)arg;
|
||||
if (q->on_get) q->on_get(q, q->on_get_arg);
|
||||
}
|
||||
|
||||
// ==================== Управление очередью ====================
|
||||
|
||||
struct ll_queue* queue_new(struct UASYNC* ua, size_t hash_size, uint16_t index_offset, uint16_t index_size, char* name) {
|
||||
@@ -151,6 +157,8 @@ void queue_free(struct ll_queue* q) {
|
||||
if (old_eid) uasync_call_soon_cancel(q->ua, old_eid);
|
||||
q->empty_callback = NULL;
|
||||
q->empty_callback_arg = NULL;
|
||||
q->on_get = NULL;
|
||||
q->on_get_arg = NULL;
|
||||
|
||||
u_free(q);
|
||||
}
|
||||
@@ -552,6 +560,9 @@ struct ll_entry* queue_data_get(struct ll_queue* q) {
|
||||
if (q->count == 0 && q->empty_callback && !q->empty_call_soon_id)
|
||||
q->empty_call_soon_id = uasync_call_soon(q->ua, q, (timeout_callback_t)empty_trampoline);
|
||||
|
||||
if (q->on_get)
|
||||
uasync_call_soon(q->ua, q, (timeout_callback_t)on_get_trampoline);
|
||||
|
||||
#ifdef QUEUE_DEBUG
|
||||
queue_check_consistency(q);// !!!! for debug
|
||||
#endif
|
||||
@@ -644,6 +655,12 @@ void queue_set_empty_callback(struct ll_queue* q, queue_callback_fn cbk_fn, void
|
||||
q->empty_call_soon_id = uasync_call_soon(q->ua, q, (timeout_callback_t)empty_trampoline);
|
||||
}
|
||||
|
||||
void queue_set_on_get(struct ll_queue* q, queue_callback_fn cbk_fn, void* arg) {
|
||||
if (!q) return;
|
||||
q->on_get = cbk_fn;
|
||||
q->on_get_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;
|
||||
|
||||
Reference in new issue
Block a user