comparison xml/en/docs/dev/development_guide.xml @ 1983:7660d6390a9d

Added the "Threads" section into the development guide.
author Vladimir Homutov <vl@nginx.com>
date Wed, 03 May 2017 12:03:10 +0300
parents 28ee7ab54a90
children 98b713b0a9fa
comparison
equal deleted inserted replaced
1982:28ee7ab54a90 1983:7660d6390a9d
2828 and <literal>NGX_RECONFIGURE_SIGNAL</literal> and sent to the nginx master 2828 and <literal>NGX_RECONFIGURE_SIGNAL</literal> and sent to the nginx master
2829 process, whose pid is read from nginx pid file. 2829 process, whose pid is read from nginx pid file.
2830 </para> 2830 </para>
2831 2831
2832 </section> 2832 </section>
2833
2834 <section name="Threads" id="threads">
2835
2836 <para>
2837 It is possible to offload tasks that would otherwise block nginx worker process
2838 into a separate thread.
2839 For example, nginx may be configured to use threads to perform
2840 <link doc="../http/ngx_http_core_module.xml" id="aio">file I/O</link>.
2841 Another example is using a library that doesn't have asynchronous interface
2842 and thus cannot be normally used with nginx.
2843 Keep in mind that threads interface is a helper for existing asynchronous
2844 approach in processing client connections, and by no means a replacement.
2845 </para>
2846
2847 <para>
2848 To deal with synchronization the following wrappers over pthreads primitives
2849 are available:
2850 <programlisting>
2851 typedef pthread_mutex_t ngx_thread_mutex_t;
2852
2853 ngx_int_t ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log);
2854 ngx_int_t ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log);
2855 ngx_int_t ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log);
2856 ngx_int_t ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log);
2857
2858 typedef pthread_cond_t ngx_thread_cond_t;
2859
2860 ngx_int_t ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log);
2861 ngx_int_t ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log);
2862 ngx_int_t ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log);
2863 ngx_int_t ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx,
2864 ngx_log_t *log);
2865 </programlisting>
2866 </para>
2867
2868 <para>
2869 Instead of creating a new thread for each task, nginx implements
2870 a <link doc="../ngx_core_module.xml" id="thread_pool"/> strategy.
2871 Multiple thread pools may be configured intended for different purposes
2872 (for example, performing I/O on different sets of disks).
2873 Each thread pool is created on start and contains a limited number of threads
2874 that process a queue of tasks.
2875 When a task is completed, a predefined completion handler is called.
2876 </para>
2877
2878 <para>
2879 The <literal>src/core/ngx_thread_pool.h</literal> header file contains
2880 corresponding definitions:
2881 <programlisting>
2882 struct ngx_thread_task_s {
2883 ngx_thread_task_t *next;
2884 ngx_uint_t id;
2885 void *ctx;
2886 void (*handler)(void *data, ngx_log_t *log);
2887 ngx_event_t event;
2888 };
2889
2890 typedef struct ngx_thread_pool_s ngx_thread_pool_t;
2891
2892 ngx_thread_pool_t *ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name);
2893 ngx_thread_pool_t *ngx_thread_pool_get(ngx_cycle_t *cycle, ngx_str_t *name);
2894
2895 ngx_thread_task_t *ngx_thread_task_alloc(ngx_pool_t *pool, size_t size);
2896 ngx_int_t ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task);
2897
2898 </programlisting>
2899 At configuration time, a module willing to use threads has to obtain a
2900 reference to thread pool by calling
2901 <literal>ngx_thread_pool_add(cf, name)</literal> which will either create a
2902 new thread pool with given <literal>name</literal> or return a reference
2903 to an existing one if a pool with such name already exists.
2904 </para>
2905
2906 <para>
2907 At runtime, the <literal>ngx_thread_task_post(tp, task)</literal> function
2908 is used to add a <literal>task</literal> into a queue of a thread pool
2909 <literal>tp</literal>.
2910
2911 The <literal>ngx_thread_task_t</literal> structure contains all necessary
2912 to execute user function in thread, pass parameters and setup completion
2913 handler:
2914 <programlisting>
2915 typedef struct {
2916 int foo;
2917 } my_thread_ctx_t;
2918
2919
2920 static void
2921 my_thread_func(void *data, ngx_log_t *log)
2922 {
2923 my_thread_ctx_t *ctx = data;
2924
2925 /* this function is executed in a separate thread */
2926 }
2927
2928
2929 static void
2930 my_thread_completion(ngx_event_t *ev)
2931 {
2932 my_thread_ctx_t *ctx = ev->data;
2933
2934 /* executed in nginx event loop */
2935 }
2936
2937
2938 ngx_int_t
2939 my_task_offload(my_conf_t *conf)
2940 {
2941 my_thread_ctx_t *ctx;
2942 ngx_thread_task_t *task;
2943
2944 task = ngx_thread_task_alloc(conf->pool, sizeof(my_thread_ctx_t));
2945 if (task == NULL) {
2946 return NGX_ERROR;
2947 }
2948
2949 ctx = task->ctx;
2950
2951 ctx->foo = 42;
2952
2953 task->handler = my_thread_func;
2954 task->event.handler = my_thread_completion;
2955 task->event.data = ctx;
2956
2957 if (ngx_thread_task_post(conf->thread_pool, task) != NGX_OK) {
2958 return NGX_ERROR;
2959 }
2960
2961 return NGX_OK;
2962 }
2963 </programlisting>
2964
2965 </para>
2966
2967 </section>
2968
2833 2969
2834 <section name="Modules" id="Modules"> 2970 <section name="Modules" id="Modules">
2835 2971
2836 <section name="Adding new modules" id="adding_new_modules"> 2972 <section name="Adding new modules" id="adding_new_modules">
2837 <para> 2973 <para>