# HG changeset patch # User Vladimir Homutov # Date 1493802190 -10800 # Node ID 7660d6390a9da2475fd5dd96754852fe17e481e3 # Parent 28ee7ab54a90ae90ffa01faf0a6d80976c63eac9 Added the "Threads" section into the development guide. diff -r 28ee7ab54a90 -r 7660d6390a9d xml/en/docs/dev/development_guide.xml --- a/xml/en/docs/dev/development_guide.xml Tue May 02 16:25:33 2017 +0300 +++ b/xml/en/docs/dev/development_guide.xml Wed May 03 12:03:10 2017 +0300 @@ -2831,6 +2831,142 @@ +
+ + +It is possible to offload tasks that would otherwise block nginx worker process +into a separate thread. +For example, nginx may be configured to use threads to perform +file I/O. +Another example is using a library that doesn't have asynchronous interface +and thus cannot be normally used with nginx. +Keep in mind that threads interface is a helper for existing asynchronous +approach in processing client connections, and by no means a replacement. + + + +To deal with synchronization the following wrappers over pthreads primitives +are available: + +typedef pthread_mutex_t ngx_thread_mutex_t; + +ngx_int_t ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log); +ngx_int_t ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log); + +typedef pthread_cond_t ngx_thread_cond_t; + +ngx_int_t ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log); +ngx_int_t ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx, + ngx_log_t *log); + + + + +Instead of creating a new thread for each task, nginx implements +a strategy. +Multiple thread pools may be configured intended for different purposes +(for example, performing I/O on different sets of disks). +Each thread pool is created on start and contains a limited number of threads +that process a queue of tasks. +When a task is completed, a predefined completion handler is called. + + + +The src/core/ngx_thread_pool.h header file contains +corresponding definitions: + +struct ngx_thread_task_s { + ngx_thread_task_t *next; + ngx_uint_t id; + void *ctx; + void (*handler)(void *data, ngx_log_t *log); + ngx_event_t event; +}; + +typedef struct ngx_thread_pool_s ngx_thread_pool_t; + +ngx_thread_pool_t *ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name); +ngx_thread_pool_t *ngx_thread_pool_get(ngx_cycle_t *cycle, ngx_str_t *name); + +ngx_thread_task_t *ngx_thread_task_alloc(ngx_pool_t *pool, size_t size); +ngx_int_t ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task); + + +At configuration time, a module willing to use threads has to obtain a +reference to thread pool by calling +ngx_thread_pool_add(cf, name) which will either create a +new thread pool with given name or return a reference +to an existing one if a pool with such name already exists. + + + +At runtime, the ngx_thread_task_post(tp, task) function +is used to add a task into a queue of a thread pool +tp. + +The ngx_thread_task_t structure contains all necessary +to execute user function in thread, pass parameters and setup completion +handler: + +typedef struct { + int foo; +} my_thread_ctx_t; + + +static void +my_thread_func(void *data, ngx_log_t *log) +{ + my_thread_ctx_t *ctx = data; + + /* this function is executed in a separate thread */ +} + + +static void +my_thread_completion(ngx_event_t *ev) +{ + my_thread_ctx_t *ctx = ev->data; + + /* executed in nginx event loop */ +} + + +ngx_int_t +my_task_offload(my_conf_t *conf) +{ + my_thread_ctx_t *ctx; + ngx_thread_task_t *task; + + task = ngx_thread_task_alloc(conf->pool, sizeof(my_thread_ctx_t)); + if (task == NULL) { + return NGX_ERROR; + } + + ctx = task->ctx; + + ctx->foo = 42; + + task->handler = my_thread_func; + task->event.handler = my_thread_completion; + task->event.data = ctx; + + if (ngx_thread_task_post(conf->thread_pool, task) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + + + + +
+ +