1e254a845SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2e254a845SShuo Chen// 3e254a845SShuo Chen// Use of this source code is governed by a BSD-style license 4e254a845SShuo Chen// that can be found in the License file. 5e254a845SShuo Chen// 6e254a845SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7e254a845SShuo Chen 8e254a845SShuo Chen#include "Poller.h" 9e254a845SShuo Chen 10e254a845SShuo Chen#include "Channel.h" 11e254a845SShuo Chen#include "logging/Logging.h" 12e254a845SShuo Chen 13e254a845SShuo Chen#include <assert.h> 14e254a845SShuo Chen#include <poll.h> 15e254a845SShuo Chen 16e254a845SShuo Chenusing namespace muduo; 17e254a845SShuo Chen 18e254a845SShuo ChenPoller::Poller(EventLoop* loop) 19e254a845SShuo Chen : ownerLoop_(loop) 20e254a845SShuo Chen{ 21e254a845SShuo Chen} 22e254a845SShuo Chen 23e254a845SShuo ChenPoller::~Poller() 24e254a845SShuo Chen{ 25e254a845SShuo Chen} 26e254a845SShuo Chen 27e254a845SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 28e254a845SShuo Chen{ 29e254a845SShuo Chen // XXX pollfds_ shouldn't change 30e254a845SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 31e254a845SShuo Chen Timestamp now(Timestamp::now()); 32e254a845SShuo Chen if (numEvents > 0) { 33e254a845SShuo Chen LOG_TRACE << numEvents << " events happended"; 34e254a845SShuo Chen fillActiveChannels(numEvents, activeChannels); 35e254a845SShuo Chen } else if (numEvents == 0) { 36e254a845SShuo Chen LOG_TRACE << " nothing happended"; 37e254a845SShuo Chen } else { 38e254a845SShuo Chen LOG_SYSERR << "Poller::poll()"; 39e254a845SShuo Chen } 40e254a845SShuo Chen return now; 41e254a845SShuo Chen} 42e254a845SShuo Chen 43e254a845SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 44e254a845SShuo Chen ChannelList* activeChannels) const 45e254a845SShuo Chen{ 46e254a845SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 47e254a845SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 48e254a845SShuo Chen { 49e254a845SShuo Chen if (pfd->revents > 0) 50e254a845SShuo Chen { 51e254a845SShuo Chen --numEvents; 52e254a845SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 53e254a845SShuo Chen assert(ch != channels_.end()); 54e254a845SShuo Chen Channel* channel = ch->second; 55e254a845SShuo Chen assert(channel->fd() == pfd->fd); 56e254a845SShuo Chen channel->set_revents(pfd->revents); 57e254a845SShuo Chen // pfd->revents = 0; 58e254a845SShuo Chen activeChannels->push_back(channel); 59e254a845SShuo Chen } 60e254a845SShuo Chen } 61e254a845SShuo Chen} 62e254a845SShuo Chen 63e254a845SShuo Chenvoid Poller::updateChannel(Channel* channel) 64e254a845SShuo Chen{ 65e254a845SShuo Chen assertInLoopThread(); 66e254a845SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67e254a845SShuo Chen if (channel->index() < 0) { 68e254a845SShuo Chen // a new one, add to pollfds_ 69e254a845SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 70e254a845SShuo Chen struct pollfd pfd; 71e254a845SShuo Chen pfd.fd = channel->fd(); 72e254a845SShuo Chen pfd.events = static_cast<short>(channel->events()); 73e254a845SShuo Chen pfd.revents = 0; 74e254a845SShuo Chen pollfds_.push_back(pfd); 75e254a845SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 76e254a845SShuo Chen channel->set_index(idx); 77e254a845SShuo Chen channels_[pfd.fd] = channel; 78e254a845SShuo Chen } else { 79e254a845SShuo Chen // update existing one 80e254a845SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 81e254a845SShuo Chen assert(channels_[channel->fd()] == channel); 82e254a845SShuo Chen int idx = channel->index(); 83e254a845SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 84e254a845SShuo Chen struct pollfd& pfd = pollfds_[idx]; 85e254a845SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 86e254a845SShuo Chen pfd.events = static_cast<short>(channel->events()); 87e254a845SShuo Chen pfd.revents = 0; 88e254a845SShuo Chen if (channel->isNoneEvent()) { 89e254a845SShuo Chen // ignore this pollfd 90e254a845SShuo Chen pfd.fd = -channel->fd()-1; 91e254a845SShuo Chen } 92e254a845SShuo Chen } 93e254a845SShuo Chen} 94e254a845SShuo Chen 95e254a845SShuo Chenvoid Poller::removeChannel(Channel* channel) 96e254a845SShuo Chen{ 97e254a845SShuo Chen assertInLoopThread(); 98e254a845SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 99e254a845SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 100e254a845SShuo Chen assert(channels_[channel->fd()] == channel); 101e254a845SShuo Chen assert(channel->isNoneEvent()); 102e254a845SShuo Chen int idx = channel->index(); 103e254a845SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 104e254a845SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 105e254a845SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 106e254a845SShuo Chen size_t n = channels_.erase(channel->fd()); 107e254a845SShuo Chen assert(n == 1); (void)n; 108e254a845SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 109e254a845SShuo Chen pollfds_.pop_back(); 110e254a845SShuo Chen } else { 111e254a845SShuo Chen int channelAtEnd = pollfds_.back().fd; 112e254a845SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113e254a845SShuo Chen if (channelAtEnd < 0) { 114e254a845SShuo Chen channelAtEnd = -channelAtEnd-1; 115e254a845SShuo Chen } 116e254a845SShuo Chen channels_[channelAtEnd]->set_index(idx); 117e254a845SShuo Chen pollfds_.pop_back(); 118e254a845SShuo Chen } 119e254a845SShuo Chen} 120e254a845SShuo Chen 121