上回说到要说 gearman 如果利用libevent 编写网络框架。但是在说之前还得先说一下 gearman如何使用多线程,
不说了上代码。
uint32_t x= 0;
do
{
gearmand->ret= gearmand_thread_create(*gearmand);
if (gearmand->ret != GEARMAND_SUCCESS)
return gearmand->ret;
x++;
}
while (x < gearmand->threads);
这快就是接入线程逻辑的入口 可以看出当 thread == 0的时候只会创建创建1一个工作线程。
gearmand_thread_st* thread= new (std::nothrow) gearmand_thread_st(gearmand);
if (thread == NULL)
{
return gearmand_merror("new", gearmand_thread_st, 1);
}
if (! gearman_server_thread_init(gearmand_server(&gearmand), &(thread->server_thread),
_log, thread, gearmand_connection_watch))
{
delete thread;
gearmand_fatal("gearman_server_thread_init(NULL)");
return GEARMAND_MEMORY_ALLOCATION_FAILURE;
}
这是创建 thread对象和初始化thread数据需要关注的是 gearmand_connection_watch这个函数请注意。主线程accept的fd 将会发给这个函数 进行吞吐数据。
if (gearmand_failed(ret= _wakeup_init(thread)))
{
gearmand_thread_free(thread);
return ret;
}
那主线程和工作线程如何进行交互的那请看 _wakeup_init这里将会建立 pip 进行命令通知。
gearmand_debug("Creating IO thread wakeup pipe");
#if defined(HAVE_PIPE2) && HAVE_PIPE2
if (pipe2(thread->wakeup_fd, O_NONBLOCK) == -1)
{
return gearmand_perror(errno, "pipe");
}
#else
if (pipe(thread->wakeup_fd) == -1)
{
return gearmand_perror(errno, "pipe");
}
gearmand_error_t local_ret;
if ((local_ret= gearmand_sockfd_nonblock(thread->wakeup_fd[0])))
{
return local_ret;
}
#endif
event_set(&(thread->wakeup_event), thread->wakeup_fd[0], EV_READ | EV_PERSIST,
_wakeup_event, thread);
if (event_base_set(thread->base, &(thread->wakeup_event)) == -1)
{
gearmand_perror(errno, "event_base_set");
}
if (event_add(&(thread->wakeup_event), NULL) < 0)
{
gearmand_perror(errno, "event_add");
return GEARMAND_EVENT;
}
thread->is_wakeup_event= true;
return GEARMAND_SUCCESS;
然后将pip放到 gearmand_thread_st 结构体中 pthread_ret= pthread_create(&(thread->id), NULL, _thread, thread);
if (pthread_ret != 0)
{
thread->count= 0;
gearmand_thread_free(thread);
return gearmand_perror(pthread_ret, "pthread_create");
}
然后将gearmand_thread_st 做为主线程和子线程的共享数据。当然这个必须要用到锁来保证共享数据的安全
int pthread_ret= pthread_mutex_init(&(thread->lock), NULL);
if (pthread_ret != 0)
{
thread->count= 0;
gearmand_thread_free(thread);
return gearmand_fatal_perror(pthread_ret, "pthread_mutex_init");
}
然后再 create_thread中利用libevent 建立 event loop
pthread_ret= pthread_create(&(thread->id), NULL, _thread, thread);
if (pthread_ret != 0)
{
thread->count= 0;
gearmand_thread_free(thread);
return gearmand_perror(pthread_ret, "pthread_create");
}
static void *_thread(void *data)
{
gearmand_thread_st *thread= (gearmand_thread_st *)data;
char buffer[BUFSIZ];
int length= snprintf(buffer, sizeof(buffer), "[%6u ]", thread->count);
if (length <= 0 or sizeof(length) >= sizeof(buffer))
{
assert(0);
buffer[0]= 0;
}
(void)gearmand_initialize_thread_logging(buffer);
gearmand_debug("Entering thread event loop");
if (event_base_loop(thread->base, 0) == -1)
{
gearmand_fatal("event_base_loop(-1)");
Gearmand()->ret= GEARMAND_EVENT;
}
gearmand_debug("Exiting thread event loop");
return NULL;
}
下回在细说 gearman的网络框架。