Poller.cc revision b37003a7
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()); 32b37003a7SShuo Chen if (numEvents > 0) 33b37003a7SShuo Chen { 34b37003a7SShuo Chen LOG_TRACE << numEvents << " events happended"; 35b37003a7SShuo Chen fillActiveChannels(numEvents, activeChannels); 36b37003a7SShuo Chen } 37b37003a7SShuo Chen else if (numEvents == 0) 38b37003a7SShuo Chen { 39b37003a7SShuo Chen LOG_TRACE << " nothing happended"; 40b37003a7SShuo Chen } 41b37003a7SShuo Chen else 42b37003a7SShuo Chen { 43b37003a7SShuo Chen LOG_SYSERR << "Poller::poll()"; 44b37003a7SShuo Chen } 45b37003a7SShuo Chen return now; 46b37003a7SShuo Chen} 47b37003a7SShuo Chen 48b37003a7SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 49b37003a7SShuo Chen ChannelList* activeChannels) const 50b37003a7SShuo Chen{ 51b37003a7SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 52b37003a7SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 53b37003a7SShuo Chen { 54b37003a7SShuo Chen if (pfd->revents > 0) 55b37003a7SShuo Chen { 56b37003a7SShuo Chen --numEvents; 57b37003a7SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 58b37003a7SShuo Chen assert(ch != channels_.end()); 59b37003a7SShuo Chen Channel* channel = ch->second; 60b37003a7SShuo Chen assert(channel->fd() == pfd->fd); 61b37003a7SShuo Chen channel->set_revents(pfd->revents); 62b37003a7SShuo Chen // pfd->revents = 0; 63b37003a7SShuo Chen activeChannels->push_back(channel); 64b37003a7SShuo Chen } 65b37003a7SShuo Chen } 66b37003a7SShuo Chen} 67b37003a7SShuo Chen 68b37003a7SShuo Chenvoid Poller::updateChannel(Channel* channel) 69b37003a7SShuo Chen{ 70b37003a7SShuo Chen assertInLoopThread(); 71b37003a7SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 72b37003a7SShuo Chen if (channel->index() < 0) 73b37003a7SShuo Chen { 74b37003a7SShuo Chen // a new one, add to pollfds_ 75b37003a7SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 76b37003a7SShuo Chen struct pollfd pfd; 77b37003a7SShuo Chen pfd.fd = channel->fd(); 78b37003a7SShuo Chen pfd.events = static_cast<short>(channel->events()); 79b37003a7SShuo Chen pfd.revents = 0; 80b37003a7SShuo Chen pollfds_.push_back(pfd); 81b37003a7SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 82b37003a7SShuo Chen channel->set_index(idx); 83b37003a7SShuo Chen channels_[pfd.fd] = channel; 84b37003a7SShuo Chen } 85b37003a7SShuo Chen else 86b37003a7SShuo Chen { 87b37003a7SShuo Chen // update existing one 88b37003a7SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 89b37003a7SShuo Chen assert(channels_[channel->fd()] == channel); 90b37003a7SShuo Chen int idx = channel->index(); 91b37003a7SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 92b37003a7SShuo Chen struct pollfd& pfd = pollfds_[idx]; 93b37003a7SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 94b37003a7SShuo Chen pfd.events = static_cast<short>(channel->events()); 95b37003a7SShuo Chen pfd.revents = 0; 96b37003a7SShuo Chen if (channel->isNoneEvent()) 97b37003a7SShuo Chen { 98b37003a7SShuo Chen // ignore this pollfd 99b37003a7SShuo Chen pfd.fd = -channel->fd()-1; 100b37003a7SShuo Chen } 101b37003a7SShuo Chen } 102b37003a7SShuo Chen} 103b37003a7SShuo Chen 104b37003a7SShuo Chenvoid Poller::removeChannel(Channel* channel) 105b37003a7SShuo Chen{ 106b37003a7SShuo Chen assertInLoopThread(); 107b37003a7SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 108b37003a7SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 109b37003a7SShuo Chen assert(channels_[channel->fd()] == channel); 110b37003a7SShuo Chen assert(channel->isNoneEvent()); 111b37003a7SShuo Chen int idx = channel->index(); 112b37003a7SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 113b37003a7SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 114b37003a7SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 115b37003a7SShuo Chen size_t n = channels_.erase(channel->fd()); 116b37003a7SShuo Chen assert(n == 1); (void)n; 117b37003a7SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) 118b37003a7SShuo Chen { 119b37003a7SShuo Chen pollfds_.pop_back(); 120b37003a7SShuo Chen } 121b37003a7SShuo Chen else 122b37003a7SShuo Chen { 123b37003a7SShuo Chen int channelAtEnd = pollfds_.back().fd; 124b37003a7SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 125b37003a7SShuo Chen if (channelAtEnd < 0) 126b37003a7SShuo Chen { 127b37003a7SShuo Chen channelAtEnd = -channelAtEnd-1; 128b37003a7SShuo Chen } 129b37003a7SShuo Chen channels_[channelAtEnd]->set_index(idx); 130b37003a7SShuo Chen pollfds_.pop_back(); 131b37003a7SShuo Chen } 132b37003a7SShuo Chen} 133b37003a7SShuo Chen 134