Browse Source

Reserve worker completions before starting background tasks

master
evgeny 1 week ago
parent
commit
00e890e0c3
  1. 32
      lib/u_async.c
  2. 7
      lib/u_async.h

32
lib/u_async.c

@ -1853,10 +1853,15 @@ void uasync_post(struct UASYNC* ua, uasync_post_callback_t callback, void* arg)
if (!ua || !callback) return;
struct posted_task* task = u_malloc(sizeof(struct posted_task));
if (!task) return;
if (!task) { DEBUG_ERROR(DEBUG_CATEGORY_SYS, "uasync_post: task allocation failed"); return; }
task->callback = callback;
task->arg = arg;
uasync_post_reserved(ua, task);
}
/* Worker резервирует completion до запуска, поэтому завершение не требует памяти. */
void uasync_post_reserved(struct UASYNC* ua, struct posted_task* task) {
task->next = NULL;
#ifdef _WIN32
@ -1883,6 +1888,31 @@ void uasync_post(struct UASYNC* ua, uasync_post_callback_t callback, void* arg)
uasync_wakeup(ua); // будим mainloop
}
/* Владелец отменяет pending completion после join производителя вне callbacks. */
err_t uasync_cancel_post(struct UASYNC* ua, struct posted_task* task) {
#ifdef _WIN32
EnterCriticalSection(&ua->posted_lock);
#else
pthread_mutex_lock(&ua->posted_lock);
#endif
struct posted_task** p = &ua->posted_tasks_head;
struct posted_task* previous = NULL;
while (*p && *p != task) { previous = *p; p = &(*p)->next; }
int found = *p != NULL;
if (found) {
*p = task->next;
if (ua->posted_tasks_tail == task) ua->posted_tasks_tail = previous;
}
#ifdef _WIN32
LeaveCriticalSection(&ua->posted_lock);
#else
pthread_mutex_unlock(&ua->posted_lock);
#endif
if (found) u_free(task);
else DEBUG_ERROR(DEBUG_CATEGORY_SYS, "uasync_cancel_post: completion is not pending");
return found ? ERR_OK : ERR_FAIL;
}
// Wakeup mechanism
int uasync_wakeup(struct UASYNC* ua) {
if (!ua || !ua->wakeup_initialized) return -1;

7
lib/u_async.h

@ -147,6 +147,13 @@ int uasync_get_wakeup_fd(struct UASYNC* ua); // returns write fd for wakeup pipe
// сообщить async (из другого thread) чтобы он вызвал callback с аргументом
void uasync_post(struct UASYNC* ua, uasync_post_callback_t callback, void* user_arg);
/* Передать заранее выделенный u_malloc task без аллокаций. uasync освобождает
* task после callback. Производитель больше не обращается к task после передачи.
* Отмена — в потоке владельца вне callbacks, после завершения производителя;
* ERR_OK означает, что task удалён из очереди и освобождён. */
void uasync_post_reserved(struct UASYNC* ua, struct posted_task* task);
err_t uasync_cancel_post(struct UASYNC* ua, struct posted_task* task);
// синхронизация памяти (для доступности из других потоков)
void uasync_memsync(struct UASYNC* ua);

Loading…
Cancel
Save