memcached 中如何使用libevent实现多线程

        最近在一直在看libevent的源码说实在的比较难,主要是开源代码的注解比较少所以细节有时 候不太懂,不过这些不妨碍我们对整个框架的了解。

          大体看过源代码后发现整个libevent是采用单线程写的,那么如何使用libevent实现多线程呢?百度后发现memcache的IO事件部分是用libevent实现的所以有看了下memcahce的IO部分。memcache的IO部分采用的,消息+同步队列来实现的。仿照这个模式写了一个简单IO事件程序。服务器端程序如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LISTAE_SOKCET_NUM 3
#define MAX_THREAD 10

struct receive_queue
{
		int thread_id;
		struct sockaddr receive_addr;
		int receivefd;
};

typedef struct
{
		int thread_id;
		int notify_receive_fd;
		int notify_send_fd;
		struct event notify_event;
		struct event_base *base;
} LIBEVENT_THREAD;


LIBEVENT_THREAD *thread;
struct timeval tv;
struct event main_event;
struct event_base * main_base;

void thread_libevent_process(int fd, short event,void *arg)
{
	LIBEVENT_THREAD * me = (LIBEVENT_THREAD *)arg;
	
		fd = me->notify_receive_fd;
		char temp[2];
		read(fd,temp, 1);
		printf("the thread_id is %d and the read data is %c \n", me->thread_id, temp[0]);
}

static void setup_thread(LIBEVENT_THREAD * thread, int idx)
{
		int i;
		thread->thread_id = idx;
		thread->base = event_init();
		event_set(&thread->notify_event, thread->notify_receive_fd, EV_READ|EV_PERSIST, thread_libevent_process, thread);
		event_base_set(thread->base, &thread->notify_event);
		if(event_add(&thread->notify_event,0) == -1)
		{
				perror("can't add event\n");
				exit(0);
		}
}

static void *work_thread( void *arg)
{
		LIBEVENT_THREAD *me = (LIBEVENT_THREAD *)arg;
		event_base_loop(me->base, 0);
}

static void thread_init()
{
		int i;
		thread =(LIBEVENT_THREAD *)malloc(sizeof(LIBEVENT_THREAD)*MAX_THREAD);
		for( i =0; i< MAX_THREAD; i++)
		{
				 pthread_t id;
				int fds[2];
				if(pipe(fds))
				{
					perror("cant't create pipe\n ");
					exit(0);
				}
				thread[i].thread_id = i;
				thread[i].notify_receive_fd = fds[0];
				thread[i].notify_send_fd = fds[1]; 
				setup_thread(&thread[i], i);

				pthread_create(&id, NULL, work_thread, &thread[i]);
		}
}

int latest_thread_id = 0; 
//****************socket create*************************************
int  socketcreate() 
{
		int i;
		int fd;
		struct sockaddr_in server;
		memset(&server, 0, sizeof(struct sockaddr_in));
		server.sin_family = AF_INET;
		server.sin_port = htons(8000);
		server.sin_addr.s_addr = htonl(INADDR_ANY);

		if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
		{
				perror("socket error\n");
				exit(0);
		}

        	if(bind(fd, (struct sockaddr*)&server, sizeof(struct sockaddr)) == -1)
    	        {
			perror("bind error\n");
			exit(0);
		}

		if(listen(fd,4)== -1)
		{
			perror("listen error\n");
			exit(0);
		}

		return fd;
}


void sig_handler(const int sig)
{
		printf("receive signal\n");
		exit(0);
		
}

void drive_machine()
{
		struct sockaddr recevie_addr1;
		socklen_t len;
		int stop = 0;
		int fd = 	socketcreate();
		signal(SIGINT, sig_handler);
		while(!stop)
		{
		 printf("begin  accept \n");
		 int recevie_fd = accept(fd, &recevie_addr1, &len);
		
			if(recevie_fd != -1)
          	        {
					
					int id = (latest_thread_id +1)%MAX_THREAD;   //thread chose used in memcache
				        latest_thread_id++;
					
					
					 write(thread[id].notify_send_fd, "c",1);  //notify  thread
			}
			else
			{
					perror("accept error");
					exit(0);
			}
		}
}

//*************************set timer not used*****************************************
static void  dispatch_thread(int fd, short event, void *arg)
{
		printf("time wakeup\n");
		int id = (latest_thread_id +1)%MAX_THREAD;
		latest_thread_id++;
		write(thread[id].notify_send_fd, "c", 1 );
		tv.tv_sec =2;
		tv.tv_usec = 0;
		event_add(&main_event, &tv);

}
//*********************************************************************8
int main()
{
	thread_init();
	/*
	tv.tv_sec = 2;
	tv.tv_usec = 0;
	main_base = event_init();
	evtimer_set(&main_event,dispatch_thread, NULL);
	event_add(&main_event, &tv);
	event_base_loop(main_base, 0);
*/
	drive_machine();
	return 0;
}	

测试程序如下:

#!/usr/bin/python
import time
from socket import *

class socket_create:
	time1 = 0
	def socket_init(self):
		for i in range(1,30):

			try:
				fd = socket()
				host = gethostname()
				port  = 8000
				fd.connect((host,port))
				fd.send("hello")
			except:
				print "socket error"
			finally:
				fd.close()
				self.time1 = self.time1 +1
				print "the " + str(self.time1)+"'s " + " time connect"
			time.sleep(2)
if __name__ == "__main__":
		Connect = socket_create()
		Connect.socket_init()


结果:

memcached 中如何使用libevent实现多线程_第1张图片


 

         

 

你可能感兴趣的:(libevent)