cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

lws-threadpool.h (10272B)


      1/*
      2 * libwebsockets - small server side websockets and web server implementation
      3 *
      4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to
      8 * deal in the Software without restriction, including without limitation the
      9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     10 * sell copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     22 * IN THE SOFTWARE.
     23 */
     24
     25/** \defgroup threadpool Threadpool related functions
     26 * ##Threadpool
     27 * \ingroup lwsapi
     28 *
     29 * This allows you to create one or more pool of threads which can run tasks
     30 * associated with a wsi.  If the pool is busy, tasks wait on a queue.
     31 *
     32 * Tasks don't have to be atomic, if they will take more than a few tens of ms
     33 * they should return back to the threadpool worker with a return of 0.  This
     34 * will allow them to abort cleanly.
     35 */
     36//@{
     37
     38struct lws_threadpool;
     39struct lws_threadpool_task;
     40
     41enum lws_threadpool_task_status {
     42	LWS_TP_STATUS_QUEUED,
     43	LWS_TP_STATUS_RUNNING,
     44	LWS_TP_STATUS_SYNCING,
     45	LWS_TP_STATUS_STOPPING,
     46	LWS_TP_STATUS_FINISHED, /* lws_threadpool_task_status() frees task */
     47	LWS_TP_STATUS_STOPPED, /* lws_threadpool_task_status() frees task */
     48};
     49
     50enum lws_threadpool_task_return {
     51	/** Still work to do, just confirming not being stopped */
     52	LWS_TP_RETURN_CHECKING_IN,
     53	/** Still work to do, enter cond_wait until service thread syncs.  This
     54	 * is used if you have filled your buffer(s) of data to the service
     55	 * thread and are blocked until the service thread completes sending at
     56	 * least one.
     57	 */
     58	LWS_TP_RETURN_SYNC,
     59	/** No more work to do... */
     60	LWS_TP_RETURN_FINISHED,
     61	/** Responding to request to stop */
     62	LWS_TP_RETURN_STOPPED,
     63
     64	/* OR on to indicate this task wishes to outlive its wsi */
     65	LWS_TP_RETURN_FLAG_OUTLIVE = 64
     66};
     67
     68struct lws_threadpool_create_args {
     69	int threads;
     70	int max_queue_depth;
     71};
     72
     73struct lws_threadpool_task_args {
     74#if defined(LWS_WITH_SECURE_STREAMS)
     75	struct lws_ss_handle *ss; /**< either wsi or ss must be set */
     76#endif
     77	struct lws *wsi;	/**< either wsi or ss must be set */
     78
     79	void *user;		/**< user may set (user-private pointer) */
     80	const char *name;	/**< user may set to describe task */
     81	char async_task;	/**< set to allow the task to shrug off the loss
     82				     of the associated wsi and continue to
     83				     completion */
     84	enum lws_threadpool_task_return (*task)(void *user,
     85					enum lws_threadpool_task_status s);
     86	/**< user must set to actual task function */
     87	void (*cleanup)(struct lws *wsi, void *user);
     88	/**< socket lifecycle may end while task is not stoppable, so the task
     89	 * must be able to detach from any wsi and clean itself up when it does
     90	 * stop.  If NULL, no cleanup necessary, otherwise point to a user-
     91	 * supplied function that destroys the stuff in \p user.
     92	 *
     93	 * wsi may be NULL on entry, indicating the task got detached due to the
     94	 * wsi closing before.
     95	 */
     96};
     97
     98/**
     99 * lws_threadpool_create() - create a pool of worker threads
    100 *
    101 * \param context: the lws_context the threadpool will exist inside
    102 * \param args: argument struct prepared by caller
    103 * \param format: printf-type format for the task name
    104 * \param ...: printf type args for the task name format
    105 *
    106 * Creates a pool of worker threads with \p threads and a queue of up to
    107 * \p max_queue_depth waiting tasks if all the threads are busy.
    108 *
    109 * Returns NULL if OOM, or a struct lws_threadpool pointer that must be
    110 * destroyed by lws_threadpool_destroy().
    111 */
    112LWS_VISIBLE LWS_EXTERN struct lws_threadpool *
    113lws_threadpool_create(struct lws_context *context,
    114		      const struct lws_threadpool_create_args *args,
    115		      const char *format, ...) LWS_FORMAT(3);
    116
    117/**
    118 * lws_threadpool_finish() - Stop all pending and running tasks
    119 *
    120 * \param tp: the threadpool object
    121 *
    122 * Marks the threadpool as under destruction.  Removes everything from the
    123 * pending queue and completes those tasks as LWS_TP_STATUS_STOPPED.
    124 *
    125 * Running tasks will also get LWS_TP_STATUS_STOPPED as soon as they
    126 * "resurface".
    127 *
    128 * This doesn't reap tasks or free the threadpool, the reaping is done by the
    129 * lws_threadpool_task_status() on the done task.
    130 */
    131LWS_VISIBLE LWS_EXTERN void
    132lws_threadpool_finish(struct lws_threadpool *tp);
    133
    134/**
    135 * lws_threadpool_destroy() - Destroy a threadpool
    136 *
    137 * \param tp: the threadpool object
    138 *
    139 * Waits for all worker threads to stop, ends the threads and frees the tp.
    140 */
    141LWS_VISIBLE LWS_EXTERN void
    142lws_threadpool_destroy(struct lws_threadpool *tp);
    143
    144/**
    145 * lws_threadpool_enqueue() - Queue the task and run it on a worker thread when possible
    146 *
    147 * \param tp: the threadpool to queue / run on
    148 * \param args: information about what to run
    149 * \param format: printf-type format for the task name
    150 * \param ...: printf type args for the task name format
    151 *
    152 * This asks for a task to run ASAP on a worker thread in threadpool \p tp.
    153 *
    154 * The args defines the wsi, a user-private pointer, a timeout in secs and
    155 * a pointer to the task function.
    156 *
    157 * Returns NULL or an opaque pointer to the queued (or running, or completed)
    158 * task.
    159 *
    160 * Once a task is created and enqueued, it can only be destroyed by calling
    161 * lws_threadpool_task_status() on it after it has reached the state
    162 * LWS_TP_STATUS_FINISHED or LWS_TP_STATUS_STOPPED.
    163 */
    164LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task *
    165lws_threadpool_enqueue(struct lws_threadpool *tp,
    166		       const struct lws_threadpool_task_args *args,
    167		       const char *format, ...) LWS_FORMAT(3);
    168
    169/**
    170 * lws_threadpool_dequeue() - Dequeue or try to stop a running task
    171 *
    172 * \param wsi: the wsi whose current task we want to eliminate
    173 *
    174 * Returns 0 is the task was dequeued or already compeleted, or 1 if the task
    175 * has been asked to stop asynchronously.
    176 *
    177 * This doesn't free the task.  It only shortcuts it to state
    178 * LWS_TP_STATUS_STOPPED.  lws_threadpool_task_status() must be performed on
    179 * the task separately once it is in LWS_TP_STATUS_STOPPED to free the task.
    180 *
    181 * DEPRECATED: You should use lws_threadpool_dequeue_task() with
    182 * lws_threadpool_get_task_wsi() / _ss() if you know there can only be one task
    183 * per connection, or call it via lws_threadpool_foreach_task_wsi() / _ss() to
    184 * get the tasks bound to the connection.
    185 */
    186LWS_VISIBLE LWS_EXTERN int
    187lws_threadpool_dequeue(struct lws *wsi) LWS_WARN_DEPRECATED;
    188
    189LWS_VISIBLE LWS_EXTERN int
    190lws_threadpool_dequeue_task(struct lws_threadpool_task *task);
    191
    192
    193/**
    194 * lws_threadpool_task_status() - reap completed tasks
    195 *
    196 * \param wsi: the wsi to query the current task of
    197 * \param task: receives a pointer to the opaque task
    198 * \param user: receives a void * pointer to the task user data
    199 *
    200 * This is the equivalent of posix waitpid()... it returns the status of the
    201 * task, and if the task is in state LWS_TP_STATUS_FINISHED or
    202 * LWS_TP_STATUS_STOPPED, frees \p task.  If in another state, the task
    203 * continues to exist.
    204 *
    205 * This is designed to be called from the service thread.
    206 *
    207 * Its use is to make sure the service thread has seen the state of the task
    208 * before deleting it.
    209 *
    210 * DEPRECATED... use lws_threadpool_task_status() instead and get the task
    211 * pointer from lws_threadpool_get_task_wsi() / _ss() if you know there can only
    212 * be one, else call it via lws_threadpool_foreach_task_wsi() / _ss()
    213 */
    214LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status
    215lws_threadpool_task_status_wsi(struct lws *wsi,
    216			       struct lws_threadpool_task **task, void **user)
    217				LWS_WARN_DEPRECATED;
    218
    219LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status
    220lws_threadpool_task_status(struct lws_threadpool_task *task, void **user);
    221
    222LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status
    223lws_threadpool_task_status_noreap(struct lws_threadpool_task *task);
    224
    225/**
    226 * lws_threadpool_task_sync() - Indicate to a stalled task it may continue
    227 *
    228 * \param task: the task to unblock
    229 * \param stop: 0 = run after unblock, 1 = when he unblocks, stop him
    230 *
    231 * Inform the task that the service thread has finished with the shared data
    232 * and that the task, if blocked in LWS_TP_RETURN_SYNC, may continue.
    233 *
    234 * If the lws service context determined that the task must be aborted, it
    235 * should still call this but with stop = 1, causing the task to finish.
    236 */
    237LWS_VISIBLE LWS_EXTERN void
    238lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop);
    239
    240/**
    241 * lws_threadpool_dump() - dump the state of a threadpool to the log
    242 *
    243 * \param tp: The threadpool to dump
    244 *
    245 * This locks the threadpool and then dumps the pending queue, the worker
    246 * threads and the done queue, together with time information for how long
    247 * the tasks have been in their current state, how long they have occupied a
    248 * thread, etc.
    249 *
    250 * This only does anything on lws builds with CMAKE_BUILD_TYPE=DEBUG, otherwise
    251 * while it still exists, it's a NOP.
    252 */
    253
    254LWS_VISIBLE LWS_EXTERN void
    255lws_threadpool_dump(struct lws_threadpool *tp);
    256
    257
    258
    259LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task *
    260lws_threadpool_get_task_wsi(struct lws *wsi);
    261
    262#if defined(LWS_WITH_SECURE_STREAMS)
    263LWS_VISIBLE LWS_EXTERN struct lws_threadpool_task *
    264lws_threadpool_get_task_ss(struct lws_ss_handle *ss);
    265#endif
    266
    267
    268LWS_VISIBLE LWS_EXTERN int
    269lws_threadpool_foreach_task_wsi(struct lws *wsi, void *user,
    270				int (*cb)(struct lws_threadpool_task *task,
    271					  void *user));
    272
    273#if defined(LWS_WITH_SECURE_STREAMS)
    274LWS_VISIBLE LWS_EXTERN int
    275lws_threadpool_foreach_task_ss(struct lws_ss_handle *ss, void *user,
    276		int (*cb)(struct lws_threadpool_task *task, void *user));
    277#endif
    278
    279
    280//@}