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