Poller.cc revision 354280cf
1354280cfSShuo Chen// excerpts from http://code.google.com/p/muduo/ 2354280cfSShuo Chen// 3354280cfSShuo Chen// Use of this source code is governed by a BSD-style license 4354280cfSShuo Chen// that can be found in the License file. 5354280cfSShuo Chen// 6354280cfSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7354280cfSShuo Chen 8354280cfSShuo Chen#include "Poller.h" 9354280cfSShuo Chen 10354280cfSShuo Chen#include "Channel.h" 11354280cfSShuo Chen#include "logging/Logging.h" 12354280cfSShuo Chen 13354280cfSShuo Chen#include <assert.h> 14354280cfSShuo Chen#include <poll.h> 15354280cfSShuo Chen 16354280cfSShuo Chenusing namespace muduo; 17354280cfSShuo Chen 18354280cfSShuo ChenPoller::Poller(EventLoop* loop) 19354280cfSShuo Chen : ownerLoop_(loop) 20354280cfSShuo Chen{ 21354280cfSShuo Chen} 22354280cfSShuo Chen 23354280cfSShuo ChenPoller::~Poller() 24354280cfSShuo Chen{ 25354280cfSShuo Chen} 26354280cfSShuo Chen 27354280cfSShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 28354280cfSShuo Chen{ 29354280cfSShuo Chen // XXX pollfds_ shouldn't change 30354280cfSShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 31354280cfSShuo Chen Timestamp now(Timestamp::now()); 32354280cfSShuo Chen if (numEvents > 0) { 33354280cfSShuo Chen LOG_TRACE << numEvents << " events happended"; 34354280cfSShuo Chen fillActiveChannels(numEvents, activeChannels); 35354280cfSShuo Chen } else if (numEvents == 0) { 36354280cfSShuo Chen LOG_TRACE << " nothing happended"; 37354280cfSShuo Chen } else { 38354280cfSShuo Chen LOG_SYSERR << "Poller::poll()"; 39354280cfSShuo Chen } 40354280cfSShuo Chen return now; 41354280cfSShuo Chen} 42354280cfSShuo Chen 43354280cfSShuo Chenvoid Poller::fillActiveChannels(int numEvents, 44354280cfSShuo Chen ChannelList* activeChannels) const 45354280cfSShuo Chen{ 46354280cfSShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 47354280cfSShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 48354280cfSShuo Chen { 49354280cfSShuo Chen if (pfd->revents > 0) 50354280cfSShuo Chen { 51354280cfSShuo Chen --numEvents; 52354280cfSShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 53354280cfSShuo Chen assert(ch != channels_.end()); 54354280cfSShuo Chen Channel* channel = ch->second; 55354280cfSShuo Chen assert(channel->fd() == pfd->fd); 56354280cfSShuo Chen channel->set_revents(pfd->revents); 57354280cfSShuo Chen // pfd->revents = 0; 58354280cfSShuo Chen activeChannels->push_back(channel); 59354280cfSShuo Chen } 60354280cfSShuo Chen } 61354280cfSShuo Chen} 62354280cfSShuo Chen 63354280cfSShuo Chenvoid Poller::updateChannel(Channel* channel) 64354280cfSShuo Chen{ 65354280cfSShuo Chen assertInLoopThread(); 66354280cfSShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67354280cfSShuo Chen if (channel->index() < 0) { 68354280cfSShuo Chen // a new one, add to pollfds_ 69354280cfSShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 70354280cfSShuo Chen struct pollfd pfd; 71354280cfSShuo Chen pfd.fd = channel->fd(); 72354280cfSShuo Chen pfd.events = static_cast<short>(channel->events()); 73354280cfSShuo Chen pfd.revents = 0; 74354280cfSShuo Chen pollfds_.push_back(pfd); 75354280cfSShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 76354280cfSShuo Chen channel->set_index(idx); 77354280cfSShuo Chen channels_[pfd.fd] = channel; 78354280cfSShuo Chen } else { 79354280cfSShuo Chen // update existing one 80354280cfSShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 81354280cfSShuo Chen assert(channels_[channel->fd()] == channel); 82354280cfSShuo Chen int idx = channel->index(); 83354280cfSShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 84354280cfSShuo Chen struct pollfd& pfd = pollfds_[idx]; 85354280cfSShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 86354280cfSShuo Chen pfd.events = static_cast<short>(channel->events()); 87354280cfSShuo Chen pfd.revents = 0; 88354280cfSShuo Chen if (channel->isNoneEvent()) { 89354280cfSShuo Chen // ignore this pollfd 90354280cfSShuo Chen pfd.fd = -channel->fd()-1; 91354280cfSShuo Chen } 92354280cfSShuo Chen } 93354280cfSShuo Chen} 94354280cfSShuo Chen 95354280cfSShuo Chenvoid Poller::removeChannel(Channel* channel) 96354280cfSShuo Chen{ 97354280cfSShuo Chen assertInLoopThread(); 98354280cfSShuo Chen LOG_TRACE << "fd = " << channel->fd(); 99354280cfSShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 100354280cfSShuo Chen assert(channels_[channel->fd()] == channel); 101354280cfSShuo Chen assert(channel->isNoneEvent()); 102354280cfSShuo Chen int idx = channel->index(); 103354280cfSShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 104354280cfSShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 105354280cfSShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 106354280cfSShuo Chen size_t n = channels_.erase(channel->fd()); 107354280cfSShuo Chen assert(n == 1); (void)n; 108354280cfSShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 109354280cfSShuo Chen pollfds_.pop_back(); 110354280cfSShuo Chen } else { 111354280cfSShuo Chen int channelAtEnd = pollfds_.back().fd; 112354280cfSShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113354280cfSShuo Chen if (channelAtEnd < 0) { 114354280cfSShuo Chen channelAtEnd = -channelAtEnd-1; 115354280cfSShuo Chen } 116354280cfSShuo Chen channels_[channelAtEnd]->set_index(idx); 117354280cfSShuo Chen pollfds_.pop_back(); 118354280cfSShuo Chen } 119354280cfSShuo Chen} 120354280cfSShuo Chen 121