目录
nginx线程池
源代码在ngx_thread_pool.c中
nginx线程池简化流程
A线程准备任务—>post任务—>线程池唤醒一个线程处理–>通过回调函数通知A线程处理完毕
数据结构分析
任务
struct ngx_thread_task_s {
ngx_thread_task_t *next; //指向下一个任务
ngx_uint_t id; //任务ID
void *ctx; //任务的上下文
void (*handler)(void *data, ngx_log_t *log); //处理任务的函数句柄
ngx_event_t event; //跟任务关联的事件对象(当线程池处理成任务之后将会由主线程调用event对象的handler回调函数)
};
队列
typedef struct {
ngx_thread_task_t *first;
ngx_thread_task_t **last;
} ngx_thread_pool_queue_t;
线程池
struct ngx_thread_pool_s {
ngx_thread_mutex_t mtx; //互斥锁,用于锁定任务队列,避免竞争状态。
ngx_thread_pool_queue_t queue; //任务队列
ngx_int_t waiting; //有多少个任务正在等待处理
ngx_thread_cond_t cond; //用于通知线程池有任务需要处理
ngx_log_t *log;
ngx_str_t name; //线程池名称
ngx_uint_t threads; //线程池由多少个线程组成(线程数)
ngx_int_t max_queue; //线程池最大能处理的任务数
u_char *file; //配置文件名
ngx_uint_t line; //thread_pool配置在配置文件中的行号
};
代码分析
入口函数ngx_thread_pool_init_worker
此函数会调用线程池初始化函数
static ngx_int_t
ngx_thread_pool_init_worker(ngx_cycle_t *cycle)
{
ngx_uint_t i;
ngx_thread_pool_t **tpp;
ngx_thread_pool_conf_t *tcf;
//如果不是worker或者只有一个worker就不起用线程池
if (ngx_process != NGX_PROCESS_WORKER
&& ngx_process != NGX_PROCESS_SINGLE)
{
return NGX_OK;
}
tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_thread_pool_module);
if (tcf == NULL) {
return NGX_OK;
}
ngx_thread_pool_queue_init(&ngx_thread_pool_done); //初始化任务完成队列
tpp = tcf->pools.elts;
for (i = 0; i < tcf->pools.nelts; i++) {
if (ngx_thread_pool_init(tpp[i], cycle->log, cycle->pool) != NGX_OK) {
return NGX_ERROR;
}
}
return NGX_OK;
}
线程池初始化ngx_thread_pool_init
static ngx_int_t
ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool)
{
int err;
pthread_t tid;
ngx_uint_t n;
pthread_attr_t attr;
if (ngx_notify == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"the configured event method cannot be used with thread pools");
return NGX_ERROR;
}
/*
#define ngx_thread_pool_queue_init(q) \
(q)->first = NULL; \
(q)->last = &(q)->first
first指针赋值NULL,**last执行first的地址
*/
ngx_thread_pool_queue_init(&tp->queue); //初始化线程池队列
if (ngx_thread_mutex_create(&tp->mtx, log) != NGX_OK) {
return NGX_ERROR;
}
if (ngx_thread_cond_create(&tp->cond, log) != NGX_OK) {
(void) ngx_thread_mutex_destroy(&tp->mtx, log);
return NGX_ERROR;
}
tp->log = log;
err = pthread_attr_init(&attr);
if (err) {
ngx_log_error(NGX_LOG_ALERT, log, err