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()); 32b4a5ce52SShuo Chen if (numEvents > 0) { 33bfe73648SShuo Chen LOG_TRACE << numEvents << " events happended"; 34bfe73648SShuo Chen fillActiveChannels(numEvents, activeChannels); 35b4a5ce52SShuo Chen } else if (numEvents == 0) { 36bfe73648SShuo Chen LOG_TRACE << " nothing happended"; 37b4a5ce52SShuo Chen } else { 38bfe73648SShuo Chen LOG_SYSERR << "Poller::poll()"; 39bfe73648SShuo Chen } 40bfe73648SShuo Chen return now; 41bfe73648SShuo Chen} 42bfe73648SShuo Chen 43bfe73648SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 44bfe73648SShuo Chen ChannelList* activeChannels) const 45bfe73648SShuo Chen{ 46bfe73648SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 47bfe73648SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 48bfe73648SShuo Chen { 49bfe73648SShuo Chen if (pfd->revents > 0) 50bfe73648SShuo Chen { 51bfe73648SShuo Chen --numEvents; 52bfe73648SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 53bfe73648SShuo Chen assert(ch != channels_.end()); 54bfe73648SShuo Chen Channel* channel = ch->second; 55bfe73648SShuo Chen assert(channel->fd() == pfd->fd); 56bfe73648SShuo Chen channel->set_revents(pfd->revents); 57bfe73648SShuo Chen // pfd->revents = 0; 58bfe73648SShuo Chen activeChannels->push_back(channel); 59bfe73648SShuo Chen } 60bfe73648SShuo Chen } 61bfe73648SShuo Chen} 62bfe73648SShuo Chen 63bfe73648SShuo Chenvoid Poller::updateChannel(Channel* channel) 64bfe73648SShuo Chen{ 6517c057c3SShuo Chen assertInLoopThread(); 66bfe73648SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67b4a5ce52SShuo Chen if (channel->index() < 0) { 68bfe73648SShuo Chen // a new one, add to pollfds_ 69bfe73648SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 70bfe73648SShuo Chen struct pollfd pfd; 71bfe73648SShuo Chen pfd.fd = channel->fd(); 72bfe73648SShuo Chen pfd.events = static_cast<short>(channel->events()); 73bfe73648SShuo Chen pfd.revents = 0; 74bfe73648SShuo Chen pollfds_.push_back(pfd); 75bfe73648SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 76bfe73648SShuo Chen channel->set_index(idx); 77bfe73648SShuo Chen channels_[pfd.fd] = channel; 78b4a5ce52SShuo Chen } else { 79bfe73648SShuo Chen // update existing one 80bfe73648SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 81bfe73648SShuo Chen assert(channels_[channel->fd()] == channel); 82bfe73648SShuo Chen int idx = channel->index(); 83bfe73648SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 84bfe73648SShuo Chen struct pollfd& pfd = pollfds_[idx]; 8517c057c3SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 8617c057c3SShuo Chen pfd.events = static_cast<short>(channel->events()); 8717c057c3SShuo Chen pfd.revents = 0; 88b4a5ce52SShuo Chen if (channel->isNoneEvent()) { 89bfe73648SShuo Chen // ignore this pollfd 9017c057c3SShuo Chen pfd.fd = -channel->fd()-1; 9117c057c3SShuo Chen } 9217c057c3SShuo Chen } 9317c057c3SShuo Chen} 9417c057c3SShuo Chen 9517c057c3SShuo Chenvoid Poller::removeChannel(Channel* channel) 9617c057c3SShuo Chen{ 9717c057c3SShuo Chen assertInLoopThread(); 9817c057c3SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 9917c057c3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 10017c057c3SShuo Chen assert(channels_[channel->fd()] == channel); 10117c057c3SShuo Chen assert(channel->isNoneEvent()); 10217c057c3SShuo Chen int idx = channel->index(); 10317c057c3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 10417c057c3SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 10517c057c3SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 10617c057c3SShuo Chen size_t n = channels_.erase(channel->fd()); 10717c057c3SShuo Chen assert(n == 1); (void)n; 108b4a5ce52SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 10917c057c3SShuo Chen pollfds_.pop_back(); 110b4a5ce52SShuo Chen } else { 11117c057c3SShuo Chen int channelAtEnd = pollfds_.back().fd; 11217c057c3SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113b4a5ce52SShuo Chen if (channelAtEnd < 0) { 11417c057c3SShuo Chen channelAtEnd = -channelAtEnd-1; 115bfe73648SShuo Chen } 11617c057c3SShuo Chen channels_[channelAtEnd]->set_index(idx); 11717c057c3SShuo Chen pollfds_.pop_back(); 118bfe73648SShuo Chen } 119bfe73648SShuo Chen} 120bfe73648SShuo Chen 121