main_base = event_init();
主函数中线程相关的
thread_init(settings.num_threads, main_base);
//Initializes the thread subsystem, creating various worker threads.
void thread_init(int nthreads, struct event_base *main_base) {
int i;
pthread_t *thread;
pthread_mutex_init(&cache_lock, NULL);
pthread_mutex_init(&conn_lock, NULL);
pthread_mutex_init(&slabs_lock, NULL);
pthread_mutex_init(&stats_lock, NULL);
pthread_mutex_init(&init_lock, NULL);
pthread_cond_init(&init_cond, NULL);
pthread_mutex_init(&cqi_freelist_lock, NULL);
cqi_freelist = NULL;
threads = malloc(sizeof(LIBEVENT_THREAD) * nthreads);
if (! threads) {
perror("Can't allocate thread descriptors");
exit(1);
}
threads[0].base = main_base;
threads[0].thread_id = pthread_self();
for (i = 0; i < nthreads; i++) {
int fds[2];
if (pipe(fds)) {
perror("Can't create notify pipe");
exit(1);
}
threads[i].notify_receive_fd = fds[0];
threads[i].notify_send_fd = fds[1];
setup_thread(&threads[i]);
}
/* Create threads after we've done all the libevent setup. */
for (i = 1; i < nthreads; i++) {
create_worker(worker_libevent, &threads[i]);
}
/* Wait for all the threads to set themselves up before returning. */
pthread_mutex_lock(&init_lock);
init_count++; // main thread
while (init_count < nthreads) {
pthread_cond_wait(&init_cond, &init_lock);
}
pthread_mutex_unlock(&init_lock);
}
/*
* Set up a thread's information.
*/
static void setup_thread(LIBEVENT_THREAD *me)
{
if (! me->base)
{
me->base = event_init();
if (! me->base)
{
fprintf(stderr, "Can't allocate event base\n");
exit(1);
}
}
/* Listen for notifications from other threads */
event_set(&me->notify_event, me->notify_receive_fd,
EV_READ | EV_PERSIST, thread_libevent_process, me);
event_base_set(me->base, &me->notify_event);
if (event_add(&me->notify_event, 0) == -1)
{
fprintf(stderr, "Can't monitor libevent notify pipe\n");
exit(1);
}
cq_init(&me->new_conn_queue);
}
/*
* Creates a worker thread.
*/
static void create_worker(void *(*func)(void *), void *arg) {
pthread_t thread;
pthread_attr_t attr;
int ret;
pthread_attr_init(&attr);
if (ret = pthread_create(&thread, &attr, func, arg)) {
fprintf(stderr, "Can't create thread: %s\n",
strerror(ret));
exit(1);
}
}
static void thread_libevent_process(int fd, short which, void *arg)
{
LIBEVENT_THREAD *me = arg;
CQ_ITEM *item;
char buf[1];
if (read(fd, buf, 1) != 1)
if (settings.verbose > 0)
fprintf(stderr, "Can't read from libevent pipe\n");
if (item = cq_peek(&me->new_conn_queue))
{
conn *c = conn_new(item->sfd, item->init_state, item->event_flags,
item->read_buffer_size, item->is_udp, me->base);
if (!c)
{
if (item->is_udp)
{
fprintf(stderr, "Can't listen for events on UDP socket\n");
exit(1);
}
else
{
if (settings.verbose > 0)
{
fprintf(stderr, "Can't listen for events on fd %d\n",
item->sfd);
}
close(item->sfd);
}
}
cqi_free(item);
}
}