1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

threadpool: add return flag for outlive wsi

This commit is contained in:
Andy Green 2018-09-30 07:08:59 +08:00
parent 64ea98f11c
commit a95a76399a
3 changed files with 40 additions and 3 deletions

View file

@ -58,7 +58,10 @@ enum lws_threadpool_task_return {
/** No more work to do... */
LWS_TP_RETURN_FINISHED,
/** Responding to request to stop */
LWS_TP_RETURN_STOPPED
LWS_TP_RETURN_STOPPED,
/* OR on to indicate this task wishes to outlive its wsi */
LWS_TP_RETURN_FLAG_OUTLIVE = 64
};
struct lws_threadpool_create_args {
@ -70,6 +73,9 @@ struct lws_threadpool_task_args {
struct lws *wsi; /**< user must set to wsi task is bound to */
void *user; /**< user may set (user-private pointer) */
const char *name; /**< user may set to describe task */
char async_task; /**< set to allow the task to shrug off the loss
of the associated wsi and continue to
completion */
enum lws_threadpool_task_return (*task)(void *user,
enum lws_threadpool_task_status s);
/**< user must set to actual task function */

View file

@ -126,6 +126,13 @@ LWS_TP_RETURN_SYNC|Task wants to trigger a WRITABLE callback and block until lws
LWS_TP_RETURN_FINISHED|Task has finished, successfully as far as it goes
LWS_TP_RETURN_STOPPED|Task has finished, aborting in response to a request to stop
The SYNC or CHECKING_IN return may also have a flag `LWS_TP_RETURN_FLAG_OUTLIVE`
applied to it, which indicates to threadpool that this task wishes to remain
unstopped after the wsi closes. This is useful in the case where the task
understands it will take a long time to complete, and wants to return a
complete status and maybe close the connection, perhaps with a token identifying
the task. The task can then be monitored separately by using the token.
#### Synchronizing
The task can choose to "SYNC" with the lws service thread, in other words

View file

@ -49,6 +49,7 @@ struct lws_threadpool_task {
int late_sync_retries;
char wanted_writeable_cb;
char outlive;
};
struct lws_pool {
@ -538,17 +539,29 @@ lws_threadpool_worker(void *d)
lws_usec_t then;
int n;
if (tp->destroying || !task->args.wsi)
if (tp->destroying || !task->args.wsi) {
lwsl_info("%s: stopping on wsi gone\n", __func__);
state_transition(task, LWS_TP_STATUS_STOPPING);
}
then = lws_now_usecs();
n = task->args.task(task->args.user, task->status);
lwsl_debug(" %d, status %d\n", n, task->status);
us_accrue(&task->acc_running, then);
switch (n) {
if (n & LWS_TP_RETURN_FLAG_OUTLIVE)
task->outlive = 1;
switch (n & 7) {
case LWS_TP_RETURN_CHECKING_IN:
/* if not destroying the tp, continue */
break;
case LWS_TP_RETURN_SYNC:
if (!task->args.wsi) {
lwsl_debug("%s: task that wants to "
"outlive lost wsi asked "
"to sync: bypassed\n",
__func__);
break;
}
/* block until writable acknowledges */
then = lws_now_usecs();
lws_threadpool_worker_sync(pool, task);
@ -777,6 +790,17 @@ lws_threadpool_dequeue(struct lws *wsi)
tp = task->tp;
pthread_mutex_lock(&tp->lock); /* ======================== tpool lock */
if (task->outlive && !tp->destroying) {
/* disconnect from wsi, and wsi from task */
wsi->tp_task = NULL;
task->args.wsi = NULL;
goto bail;
}
c = &tp->task_queue_head;
/* is he queued waiting for a chance to run? Mark him as stopped and