Poller.cc revision 17c057c3
1bfe73648SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2bfe73648SShuo Chen// 3bfe73648SShuo Chen// Use of this source code is governed by a BSD-style license 4bfe73648SShuo Chen// that can be found in the License file. 5bfe73648SShuo Chen// 6bfe73648SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7bfe73648SShuo Chen 8bfe73648SShuo Chen#include "Poller.h" 9bfe73648SShuo Chen 10bfe73648SShuo Chen#include "Channel.h" 11bfe73648SShuo Chen#include "logging/Logging.h" 12bfe73648SShuo Chen 13bfe73648SShuo Chen#include <assert.h> 14bfe73648SShuo Chen#include <poll.h> 15bfe73648SShuo Chen 16bfe73648SShuo Chenusing namespace muduo; 17bfe73648SShuo Chen 18bfe73648SShuo ChenPoller::Poller(EventLoop* loop) 19bfe73648SShuo Chen : ownerLoop_(loop) 20bfe73648SShuo Chen{ 21bfe73648SShuo Chen} 22bfe73648SShuo Chen 23bfe73648SShuo ChenPoller::~Poller() 24bfe73648SShuo Chen{ 25bfe73648SShuo Chen} 26bfe73648SShuo Chen 27bfe73648SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 28bfe73648SShuo Chen{ 29bfe73648SShuo Chen // XXX pollfds_ shouldn't change 30bfe73648SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 31bfe73648SShuo Chen Timestamp now(Timestamp::now()); 32bfe73648SShuo Chen if (numEvents > 0) 33bfe73648SShuo Chen { 34bfe73648SShuo Chen LOG_TRACE << numEvents << " events happended"; 35bfe73648SShuo Chen fillActiveChannels(numEvents, activeChannels); 36bfe73648SShuo Chen } 37bfe73648SShuo Chen else if (numEvents == 0) 38bfe73648SShuo Chen { 39bfe73648SShuo Chen LOG_TRACE << " nothing happended"; 40bfe73648SShuo Chen } 41bfe73648SShuo Chen else 42bfe73648SShuo Chen { 43bfe73648SShuo Chen LOG_SYSERR << "Poller::poll()"; 44bfe73648SShuo Chen } 45bfe73648SShuo Chen return now; 46bfe73648SShuo Chen} 47bfe73648SShuo Chen 48bfe73648SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 49bfe73648SShuo Chen ChannelList* activeChannels) const 50bfe73648SShuo Chen{ 51bfe73648SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 52bfe73648SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 53bfe73648SShuo Chen { 54bfe73648SShuo Chen if (pfd->revents > 0) 55bfe73648SShuo Chen { 56bfe73648SShuo Chen --numEvents; 57bfe73648SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 58bfe73648SShuo Chen assert(ch != channels_.end()); 59bfe73648SShuo Chen Channel* channel = ch->second; 60bfe73648SShuo Chen assert(channel->fd() == pfd->fd); 61bfe73648SShuo Chen channel->set_revents(pfd->revents); 62bfe73648SShuo Chen // pfd->revents = 0; 63bfe73648SShuo Chen activeChannels->push_back(channel); 64bfe73648SShuo Chen } 65bfe73648SShuo Chen } 66bfe73648SShuo Chen} 67bfe73648SShuo Chen 68bfe73648SShuo Chenvoid Poller::updateChannel(Channel* channel) 69bfe73648SShuo Chen{ 7017c057c3SShuo Chen assertInLoopThread(); 71bfe73648SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 72bfe73648SShuo Chen if (channel->index() < 0) 73bfe73648SShuo Chen { 74bfe73648SShuo Chen // a new one, add to pollfds_ 75bfe73648SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 76bfe73648SShuo Chen struct pollfd pfd; 77bfe73648SShuo Chen pfd.fd = channel->fd(); 78bfe73648SShuo Chen pfd.events = static_cast<short>(channel->events()); 79bfe73648SShuo Chen pfd.revents = 0; 80bfe73648SShuo Chen pollfds_.push_back(pfd); 81bfe73648SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 82bfe73648SShuo Chen channel->set_index(idx); 83bfe73648SShuo Chen channels_[pfd.fd] = channel; 84bfe73648SShuo Chen } 85bfe73648SShuo Chen else 86bfe73648SShuo Chen { 87bfe73648SShuo Chen // update existing one 88bfe73648SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 89bfe73648SShuo Chen assert(channels_[channel->fd()] == channel); 90bfe73648SShuo Chen int idx = channel->index(); 91bfe73648SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 92bfe73648SShuo Chen struct pollfd& pfd = pollfds_[idx]; 9317c057c3SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 9417c057c3SShuo Chen pfd.events = static_cast<short>(channel->events()); 9517c057c3SShuo Chen pfd.revents = 0; 960615e80eSShuo Chen if (channel->isNoneEvent()) 97bfe73648SShuo Chen { 98bfe73648SShuo Chen // ignore this pollfd 9917c057c3SShuo Chen pfd.fd = -channel->fd()-1; 10017c057c3SShuo Chen } 10117c057c3SShuo Chen } 10217c057c3SShuo Chen} 10317c057c3SShuo Chen 10417c057c3SShuo Chenvoid Poller::removeChannel(Channel* channel) 10517c057c3SShuo Chen{ 10617c057c3SShuo Chen assertInLoopThread(); 10717c057c3SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 10817c057c3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 10917c057c3SShuo Chen assert(channels_[channel->fd()] == channel); 11017c057c3SShuo Chen assert(channel->isNoneEvent()); 11117c057c3SShuo Chen int idx = channel->index(); 11217c057c3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 11317c057c3SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 11417c057c3SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 11517c057c3SShuo Chen size_t n = channels_.erase(channel->fd()); 11617c057c3SShuo Chen assert(n == 1); (void)n; 11717c057c3SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) 11817c057c3SShuo Chen { 11917c057c3SShuo Chen pollfds_.pop_back(); 12017c057c3SShuo Chen } 12117c057c3SShuo Chen else 12217c057c3SShuo Chen { 12317c057c3SShuo Chen int channelAtEnd = pollfds_.back().fd; 12417c057c3SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 12517c057c3SShuo Chen if (channelAtEnd < 0) 12617c057c3SShuo Chen { 12717c057c3SShuo Chen channelAtEnd = -channelAtEnd-1; 128bfe73648SShuo Chen } 12917c057c3SShuo Chen channels_[channelAtEnd]->set_index(idx); 13017c057c3SShuo Chen pollfds_.pop_back(); 131bfe73648SShuo Chen } 132bfe73648SShuo Chen} 133bfe73648SShuo Chen 134