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