本文主要介绍了在dispatcher中的处理流程,包括线程同步以及节点的添加和操作。其中,任务队列是一个链表,每个节点包含channel类型、文件描述符和操作类型。在添加节点时,需要考虑线程同步,并确保节点被正确地添加到链表中。
// 添加任务到任务队列
int eventLoopAddTask(struct EventLoop* evLoop,struct Channel* channel,int type);
(1) 为什么在上面添加链表节点的时候需要加互斥锁?
(2) 如果当前的线程是主线程,那么我们能够让主线程进行节点的处理吗?
// 添加任务到任务队列
int eventLoopAddTask(struct EventLoop* evLoop,struct Channel* channel,int type) {
// 加锁,保护共享资源
pthread_mutex_lock(&evLoop->mutex);
// 创建新节点,后添加到任务队列中去
struct ChannelElement* node = (struct ChannelElement*)malloc(sizeof(struct ChannelElement));
node->channel = channel;
node->type = type;
node->next = NULL;
// 链表为空
if(evLoop->head == NULL) {
evLoop->head = evLoop->tail = node;
}else {
evLoop->tail->next = node; // 添加
evLoop->tail = node; // 后移
}
pthread_mutex_unlock(&evLoop->mutex);
// 处理节点
/**
* 这个描述假设了一个前提条件,就是当前的EventLoop反应堆属于子线程
* 细节:
* 1.对于链表节点的添加:可能是当前线程也可能是其他线程(主线程)
* 1).修改fd的事件,当前子线程发起,当前子线程处理
* 2).添加新的fd(意味着和一个新的客户端建立连接,这是由主线程做的,故添加任务节点这个操作肯定是由主线程做的),
* 添加任务节点的操作是由主线程发起的
* 2.不能让主线程处理任务队列里边的节点,需要由当前的子线程去处理
*/
if(evLoop->threadID == pthread_self()) {
// 当前子线程
(待续写)...
}else{
// 主线程 -- 告诉子线程处理任务队列中的任务
// 1.子线程在工作 2.子线程被阻塞了:select、poll、epoll
(待续写)...
}
return 0;
}
一、任务队列与文件描述符
二、任务队列的线程同步
三、节点的添加与操作
四、线程角色与任务处理
五、总结