Poller.cc revision 40161064
140161064SShuo Chen// excerpts from http://code.google.com/p/muduo/ 240161064SShuo Chen// 340161064SShuo Chen// Use of this source code is governed by a BSD-style license 440161064SShuo Chen// that can be found in the License file. 540161064SShuo Chen// 640161064SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 740161064SShuo Chen 840161064SShuo Chen#include "Poller.h" 940161064SShuo Chen 1040161064SShuo Chen#include "Channel.h" 1140161064SShuo Chen#include "logging/Logging.h" 1240161064SShuo Chen 1340161064SShuo Chen#include <assert.h> 1440161064SShuo Chen#include <poll.h> 1540161064SShuo Chen 1640161064SShuo Chenusing namespace muduo; 1740161064SShuo Chen 1840161064SShuo ChenPoller::Poller(EventLoop* loop) 1940161064SShuo Chen : ownerLoop_(loop) 2040161064SShuo Chen{ 2140161064SShuo Chen} 2240161064SShuo Chen 2340161064SShuo ChenPoller::~Poller() 2440161064SShuo Chen{ 2540161064SShuo Chen} 2640161064SShuo Chen 2740161064SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 2840161064SShuo Chen{ 2940161064SShuo Chen // XXX pollfds_ shouldn't change 3040161064SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 3140161064SShuo Chen Timestamp now(Timestamp::now()); 3240161064SShuo Chen if (numEvents > 0) { 3340161064SShuo Chen LOG_TRACE << numEvents << " events happended"; 3440161064SShuo Chen fillActiveChannels(numEvents, activeChannels); 3540161064SShuo Chen } else if (numEvents == 0) { 3640161064SShuo Chen LOG_TRACE << " nothing happended"; 3740161064SShuo Chen } else { 3840161064SShuo Chen LOG_SYSERR << "Poller::poll()"; 3940161064SShuo Chen } 4040161064SShuo Chen return now; 4140161064SShuo Chen} 4240161064SShuo Chen 4340161064SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 4440161064SShuo Chen ChannelList* activeChannels) const 4540161064SShuo Chen{ 4640161064SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 4740161064SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 4840161064SShuo Chen { 4940161064SShuo Chen if (pfd->revents > 0) 5040161064SShuo Chen { 5140161064SShuo Chen --numEvents; 5240161064SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 5340161064SShuo Chen assert(ch != channels_.end()); 5440161064SShuo Chen Channel* channel = ch->second; 5540161064SShuo Chen assert(channel->fd() == pfd->fd); 5640161064SShuo Chen channel->set_revents(pfd->revents); 5740161064SShuo Chen // pfd->revents = 0; 5840161064SShuo Chen activeChannels->push_back(channel); 5940161064SShuo Chen } 6040161064SShuo Chen } 6140161064SShuo Chen} 6240161064SShuo Chen 6340161064SShuo Chenvoid Poller::updateChannel(Channel* channel) 6440161064SShuo Chen{ 6540161064SShuo Chen assertInLoopThread(); 6640161064SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 6740161064SShuo Chen if (channel->index() < 0) { 6840161064SShuo Chen // a new one, add to pollfds_ 6940161064SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 7040161064SShuo Chen struct pollfd pfd; 7140161064SShuo Chen pfd.fd = channel->fd(); 7240161064SShuo Chen pfd.events = static_cast<short>(channel->events()); 7340161064SShuo Chen pfd.revents = 0; 7440161064SShuo Chen pollfds_.push_back(pfd); 7540161064SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 7640161064SShuo Chen channel->set_index(idx); 7740161064SShuo Chen channels_[pfd.fd] = channel; 7840161064SShuo Chen } else { 7940161064SShuo Chen // update existing one 8040161064SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 8140161064SShuo Chen assert(channels_[channel->fd()] == channel); 8240161064SShuo Chen int idx = channel->index(); 8340161064SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 8440161064SShuo Chen struct pollfd& pfd = pollfds_[idx]; 8540161064SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 8640161064SShuo Chen pfd.events = static_cast<short>(channel->events()); 8740161064SShuo Chen pfd.revents = 0; 8840161064SShuo Chen if (channel->isNoneEvent()) { 8940161064SShuo Chen // ignore this pollfd 9040161064SShuo Chen pfd.fd = -channel->fd()-1; 9140161064SShuo Chen } 9240161064SShuo Chen } 9340161064SShuo Chen} 9440161064SShuo Chen 9540161064SShuo Chenvoid Poller::removeChannel(Channel* channel) 9640161064SShuo Chen{ 9740161064SShuo Chen assertInLoopThread(); 9840161064SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 9940161064SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 10040161064SShuo Chen assert(channels_[channel->fd()] == channel); 10140161064SShuo Chen assert(channel->isNoneEvent()); 10240161064SShuo Chen int idx = channel->index(); 10340161064SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 10440161064SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 10540161064SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 10640161064SShuo Chen size_t n = channels_.erase(channel->fd()); 10740161064SShuo Chen assert(n == 1); (void)n; 10840161064SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 10940161064SShuo Chen pollfds_.pop_back(); 11040161064SShuo Chen } else { 11140161064SShuo Chen int channelAtEnd = pollfds_.back().fd; 11240161064SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 11340161064SShuo Chen if (channelAtEnd < 0) { 11440161064SShuo Chen channelAtEnd = -channelAtEnd-1; 11540161064SShuo Chen } 11640161064SShuo Chen channels_[channelAtEnd]->set_index(idx); 11740161064SShuo Chen pollfds_.pop_back(); 11840161064SShuo Chen } 11940161064SShuo Chen} 12040161064SShuo Chen 121