109 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			109 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | // PHZ
 | ||
|  | // 2018-5-15
 | ||
|  | 
 | ||
|  | #include "EpollTaskScheduler.h"
 | ||
|  | 
 | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | #include <sys/epoll.h>
 | ||
|  | #include <errno.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | using namespace xop; | ||
|  | 
 | ||
|  | EpollTaskScheduler::EpollTaskScheduler(int id) | ||
|  | 	: TaskScheduler(id) | ||
|  | { | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  |     epollfd_ = epoll_create(1024); | ||
|  |  #endif
 | ||
|  |     this->UpdateChannel(wakeup_channel_); | ||
|  | } | ||
|  | 
 | ||
|  | EpollTaskScheduler::~EpollTaskScheduler() | ||
|  | { | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | 	if (epollfd_ >= 0) { | ||
|  | 		close(epollfd_); | ||
|  | 		epollfd_ = -1; | ||
|  | 	} | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | void EpollTaskScheduler::UpdateChannel(ChannelPtr channel) | ||
|  | { | ||
|  | 	std::lock_guard<std::mutex> lock(mutex_); | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | 	int fd = channel->GetSocket(); | ||
|  | 	if(channels_.find(fd) != channels_.end()) { | ||
|  | 		if(channel->IsNoneEvent()) { | ||
|  | 			Update(EPOLL_CTL_DEL, channel); | ||
|  | 			channels_.erase(fd); | ||
|  | 		} | ||
|  | 		else { | ||
|  | 			Update(EPOLL_CTL_MOD, channel); | ||
|  | 		} | ||
|  | 	} | ||
|  | 	else { | ||
|  | 		if(!channel->IsNoneEvent()) { | ||
|  | 			channels_.emplace(fd, channel); | ||
|  | 			Update(EPOLL_CTL_ADD, channel); | ||
|  | 		}	 | ||
|  | 	}	 | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | void EpollTaskScheduler::Update(int operation, ChannelPtr& channel) | ||
|  | { | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | 	struct epoll_event event = {0}; | ||
|  | 
 | ||
|  | 	if(operation != EPOLL_CTL_DEL) { | ||
|  | 		event.data.ptr = channel.get(); | ||
|  | 		event.events = channel->GetEvents(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if(::epoll_ctl(epollfd_, operation, channel->GetSocket(), &event) < 0) { | ||
|  | 
 | ||
|  | 	} | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | void EpollTaskScheduler::RemoveChannel(ChannelPtr& channel) | ||
|  | { | ||
|  |     std::lock_guard<std::mutex> lock(mutex_); | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | 	int fd = channel->GetSocket(); | ||
|  | 
 | ||
|  | 	if(channels_.find(fd) != channels_.end()) { | ||
|  | 		Update(EPOLL_CTL_DEL, channel); | ||
|  | 		channels_.erase(fd); | ||
|  | 	} | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | bool EpollTaskScheduler::HandleEvent(int timeout) | ||
|  | { | ||
|  | #if defined(__linux) || defined(__linux__) 
 | ||
|  | 	struct epoll_event events[512] = {0}; | ||
|  | 	int num_events = -1; | ||
|  | 
 | ||
|  | 	num_events = epoll_wait(epollfd_, events, 512, timeout); | ||
|  | 	if(num_events < 0)  { | ||
|  | 		if(errno != EINTR) { | ||
|  | 			return false; | ||
|  | 		}								 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	for(int n=0; n<num_events; n++) { | ||
|  | 		if(events[n].data.ptr) {         | ||
|  | 			((Channel *)events[n].data.ptr)->HandleEvent(events[n].events); | ||
|  | 		} | ||
|  | 	}		 | ||
|  | 	return true; | ||
|  | #else
 | ||
|  |     return false; | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 |