EPoller.cc revision 70523619
170523619SShuo Chen// excerpts from http://code.google.com/p/muduo/ 270523619SShuo Chen// 370523619SShuo Chen// Use of this source code is governed by a BSD-style license 470523619SShuo Chen// that can be found in the License file. 570523619SShuo Chen// 670523619SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 770523619SShuo Chen 870523619SShuo Chen#include "EPoller.h" 970523619SShuo Chen 1070523619SShuo Chen#include "Channel.h" 1170523619SShuo Chen#include "logging/Logging.h" 1270523619SShuo Chen 1370523619SShuo Chen 1470523619SShuo Chen#include <boost/static_assert.hpp> 1570523619SShuo Chen 1670523619SShuo Chen#include <assert.h> 1770523619SShuo Chen#include <errno.h> 1870523619SShuo Chen#include <poll.h> 1970523619SShuo Chen#include <sys/epoll.h> 2070523619SShuo Chen 2170523619SShuo Chenusing namespace muduo; 2270523619SShuo Chen 2370523619SShuo Chen// On Linux, the constants of poll(2) and epoll(4) 2470523619SShuo Chen// are expected to be the same. 2570523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLIN == POLLIN); 2670523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLPRI == POLLPRI); 2770523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLOUT == POLLOUT); 2870523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLRDHUP == POLLRDHUP); 2970523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLERR == POLLERR); 3070523619SShuo ChenBOOST_STATIC_ASSERT(EPOLLHUP == POLLHUP); 3170523619SShuo Chen 3270523619SShuo Chennamespace 3370523619SShuo Chen{ 3470523619SShuo Chenconst int kNew = -1; 3570523619SShuo Chenconst int kAdded = 1; 3670523619SShuo Chenconst int kDeleted = 2; 3770523619SShuo Chen} 3870523619SShuo Chen 3970523619SShuo ChenEPoller::EPoller(EventLoop* loop) 4070523619SShuo Chen : ownerLoop_(loop), 4170523619SShuo Chen epollfd_(::epoll_create1(EPOLL_CLOEXEC)), 4270523619SShuo Chen events_(kInitEventListSize) 4370523619SShuo Chen{ 4470523619SShuo Chen if (epollfd_ < 0) 4570523619SShuo Chen { 4670523619SShuo Chen LOG_SYSFATAL << "EPoller::EPoller"; 4770523619SShuo Chen } 4870523619SShuo Chen} 4970523619SShuo Chen 5070523619SShuo ChenEPoller::~EPoller() 5170523619SShuo Chen{ 5270523619SShuo Chen ::close(epollfd_); 5370523619SShuo Chen} 5470523619SShuo Chen 5570523619SShuo ChenTimestamp EPoller::poll(int timeoutMs, ChannelList* activeChannels) 5670523619SShuo Chen{ 5770523619SShuo Chen int numEvents = ::epoll_wait(epollfd_, 5870523619SShuo Chen &*events_.begin(), 5970523619SShuo Chen static_cast<int>(events_.size()), 6070523619SShuo Chen timeoutMs); 6170523619SShuo Chen Timestamp now(Timestamp::now()); 6270523619SShuo Chen if (numEvents > 0) 6370523619SShuo Chen { 6470523619SShuo Chen LOG_TRACE << numEvents << " events happended"; 6570523619SShuo Chen fillActiveChannels(numEvents, activeChannels); 6670523619SShuo Chen if (implicit_cast<size_t>(numEvents) == events_.size()) 6770523619SShuo Chen { 6870523619SShuo Chen events_.resize(events_.size()*2); 6970523619SShuo Chen } 7070523619SShuo Chen } 7170523619SShuo Chen else if (numEvents == 0) 7270523619SShuo Chen { 7370523619SShuo Chen LOG_TRACE << " nothing happended"; 7470523619SShuo Chen } 7570523619SShuo Chen else 7670523619SShuo Chen { 7770523619SShuo Chen LOG_SYSERR << "EPoller::poll()"; 7870523619SShuo Chen } 7970523619SShuo Chen return now; 8070523619SShuo Chen} 8170523619SShuo Chen 8270523619SShuo Chenvoid EPoller::fillActiveChannels(int numEvents, 8370523619SShuo Chen ChannelList* activeChannels) const 8470523619SShuo Chen{ 8570523619SShuo Chen assert(implicit_cast<size_t>(numEvents) <= events_.size()); 8670523619SShuo Chen for (int i = 0; i < numEvents; ++i) 8770523619SShuo Chen { 8870523619SShuo Chen Channel* channel = static_cast<Channel*>(events_[i].data.ptr); 8970523619SShuo Chen#ifndef NDEBUG 9070523619SShuo Chen int fd = channel->fd(); 9170523619SShuo Chen ChannelMap::const_iterator it = channels_.find(fd); 9270523619SShuo Chen assert(it != channels_.end()); 9370523619SShuo Chen assert(it->second == channel); 9470523619SShuo Chen#endif 9570523619SShuo Chen channel->set_revents(events_[i].events); 9670523619SShuo Chen activeChannels->push_back(channel); 9770523619SShuo Chen } 9870523619SShuo Chen} 9970523619SShuo Chen 10070523619SShuo Chenvoid EPoller::updateChannel(Channel* channel) 10170523619SShuo Chen{ 10270523619SShuo Chen assertInLoopThread(); 10370523619SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 10470523619SShuo Chen const int index = channel->index(); 10570523619SShuo Chen if (index == kNew || index == kDeleted) 10670523619SShuo Chen { 10770523619SShuo Chen // a new one, add with EPOLL_CTL_ADD 10870523619SShuo Chen int fd = channel->fd(); 10970523619SShuo Chen if (index == kNew) 11070523619SShuo Chen { 11170523619SShuo Chen assert(channels_.find(fd) == channels_.end()); 11270523619SShuo Chen channels_[fd] = channel; 11370523619SShuo Chen } 11470523619SShuo Chen else // index == kDeleted 11570523619SShuo Chen { 11670523619SShuo Chen assert(channels_.find(fd) != channels_.end()); 11770523619SShuo Chen assert(channels_[fd] == channel); 11870523619SShuo Chen } 11970523619SShuo Chen channel->set_index(kAdded); 12070523619SShuo Chen update(EPOLL_CTL_ADD, channel); 12170523619SShuo Chen } 12270523619SShuo Chen else 12370523619SShuo Chen { 12470523619SShuo Chen // update existing one with EPOLL_CTL_MOD/DEL 12570523619SShuo Chen int fd = channel->fd(); 12670523619SShuo Chen (void)fd; 12770523619SShuo Chen assert(channels_.find(fd) != channels_.end()); 12870523619SShuo Chen assert(channels_[fd] == channel); 12970523619SShuo Chen assert(index == kAdded); 13070523619SShuo Chen if (channel->isNoneEvent()) 13170523619SShuo Chen { 13270523619SShuo Chen update(EPOLL_CTL_DEL, channel); 13370523619SShuo Chen channel->set_index(kDeleted); 13470523619SShuo Chen } 13570523619SShuo Chen else 13670523619SShuo Chen { 13770523619SShuo Chen update(EPOLL_CTL_MOD, channel); 13870523619SShuo Chen } 13970523619SShuo Chen } 14070523619SShuo Chen} 14170523619SShuo Chen 14270523619SShuo Chenvoid EPoller::removeChannel(Channel* channel) 14370523619SShuo Chen{ 14470523619SShuo Chen assertInLoopThread(); 14570523619SShuo Chen int fd = channel->fd(); 14670523619SShuo Chen LOG_TRACE << "fd = " << fd; 14770523619SShuo Chen assert(channels_.find(fd) != channels_.end()); 14870523619SShuo Chen assert(channels_[fd] == channel); 14970523619SShuo Chen assert(channel->isNoneEvent()); 15070523619SShuo Chen int index = channel->index(); 15170523619SShuo Chen assert(index == kAdded || index == kDeleted); 15270523619SShuo Chen size_t n = channels_.erase(fd); 15370523619SShuo Chen (void)n; 15470523619SShuo Chen assert(n == 1); 15570523619SShuo Chen 15670523619SShuo Chen if (index == kAdded) 15770523619SShuo Chen { 15870523619SShuo Chen update(EPOLL_CTL_DEL, channel); 15970523619SShuo Chen } 16070523619SShuo Chen channel->set_index(kNew); 16170523619SShuo Chen} 16270523619SShuo Chen 16370523619SShuo Chenvoid EPoller::update(int operation, Channel* channel) 16470523619SShuo Chen{ 16570523619SShuo Chen struct epoll_event event; 16670523619SShuo Chen bzero(&event, sizeof event); 16770523619SShuo Chen event.events = channel->events(); 16870523619SShuo Chen event.data.ptr = channel; 16970523619SShuo Chen int fd = channel->fd(); 17070523619SShuo Chen if (::epoll_ctl(epollfd_, operation, fd, &event) < 0) 17170523619SShuo Chen { 17270523619SShuo Chen if (operation == EPOLL_CTL_DEL) 17370523619SShuo Chen { 17470523619SShuo Chen LOG_SYSERR << "epoll_ctl op=" << operation << " fd=" << fd; 17570523619SShuo Chen } 17670523619SShuo Chen else 17770523619SShuo Chen { 17870523619SShuo Chen LOG_SYSFATAL << "epoll_ctl op=" << operation << " fd=" << fd; 17970523619SShuo Chen } 18070523619SShuo Chen } 18170523619SShuo Chen} 18270523619SShuo Chen 183