由于在源码中增加了部分注释,行号可能不准确,请以函数为准(仅仅在tcp模式才会用到这里初始化的资源,IPC、inproc 模式不会进行域名解析):
1. 整体功能,nng_posix_resolv_sysinit() 是nng协议的域名解析系统初始化。在协议启动时进行初始化。同函数nni_posix_pollq_sysinit一样在nni_plat_init中调用。实际上就是对全局变量 resolv_thrs 的初始化。
主要步骤:
1.设置并发量,这里默认取值为 4, 兜底保持一个线程。
2. 对上述数量的线程结构体申请空间【NNI_ALLOC_STRUCTS】,针对每个解析线程进行初始化【nni_thr_init】。
3. 依次启动域名解析线程【nni_thr_run】。
2. 代码处理过程
nng协议所有的初始化都是类似的模式,首先对 resolv_thrs 的第一层 &resolv_thr[i]->thr 进行初始化,然后对全局变量 &resolv_tghrs[i]->thr->thr 初始化。详细可以参考前面的 nni_posix_pollq_sysinit 的初始化流程。这里贴出结构体的成员变量和初始化之后的效果。值得一提的是,resolv_thr 数组的成员变量类型是 nni_thr,其定义是:
struct nni_thr{
nni_plat_thr thr;
nni_plat_mtx mtx;
nni_plat_cv cv;
nni_thr_func fn;
void *arg;
int start;
int stop;
int done;
int init;
}
第一层初始化调用函数 nni_thr_init 针对nni_thr进行初始化,在nni_thr_init中又调用函数 nni_plat_thr_init 函数对 &nni_thr->thr进行初始化, 最终初始化的效果是:
第一层初始化后的值
&resolv_thr[i]->thr->done = 0;
&resolv_thr[i]->thr->start = 0;
&resolv_thr[i]->thr->stop = 0;
&resolv_thr[i]->thr->fn = resolv_worker;
&resolv_thr[i]->thr->arg = NULL;
第二层初始化的值
&resolv_thr[i]->thr->thr->tid;
&resolv_thr[i]->thr->thr->fn = nni_thr_wrap;
&resolv_thr[i]->thr->thr->arg = &resolv_thr[i];
在nni_plat_thr_init 中, 针对 resolv_thr[i]->thr->thr进行函数指针和参数的赋值。创建了一个线程,执行线程函数 nni_plat_thr_main, 参数类型是 nni_plat_thr 也就是 &reslov_thr[i]->thr->thr
执行 赋值后的函数,也就是:&resolv_thr[i]->thr->thr->fn( &resolv_thr[i]->thr->thr->arg ) 从上面的赋值关系看,就是nni_thr_wrap(&resolv_thr[i]) .
这里贴一下nni_thr_wrap函数的定义:
static void
nni_thr_wrap(void *arg){
nni_thr *thr = arg;
int start;
nni_plat_mtx_lock(&thr->mtx);
while(((start = thr->start) == 0 && (thr->stop) == 0)){
nni_plat_cv_wait(&thr->cv);
}
nni_plat_mtx_unlock(&thr->mtx);
if((start) && (&thr->fn != NULL){
thr->fn(thr->arg);
}
nni_plat_mtx_lock(&thr->mtx);
thr->done = 1;
nni_plat_cv_wake(&thr->cv);
nni_plat_mtx_unlock(&thr->mtx);
}
在nni_thr_wrap中,由于初始化的值 (start = &nni_thr->start ) == 0 , &nni_thr->stop == 0; 因此线程将等待在条件变量 &thr-cv上。
3. 接下来 nni_thr_init 会执行 nni_thr_run(nni_thr *thr) 设置 &thr->start = 1; 并唤醒等待在
&thr-cv 上的条件变量,则nni_thr_wrap 将被唤醒,并执行 thr->fn(thr->arg) 也就是将执行resolv_worker(void *unused) 函数,并且函数参数是NULL。
流程简图