Poller.cc revision b4a5ce52
165c497a3SShuo Chen// excerpts from http://code.google.com/p/muduo/ 265c497a3SShuo Chen// 365c497a3SShuo Chen// Use of this source code is governed by a BSD-style license 465c497a3SShuo Chen// that can be found in the License file. 565c497a3SShuo Chen// 665c497a3SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 765c497a3SShuo Chen 865c497a3SShuo Chen#include "Poller.h" 965c497a3SShuo Chen 1065c497a3SShuo Chen#include "Channel.h" 1165c497a3SShuo Chen#include "logging/Logging.h" 1265c497a3SShuo Chen 1365c497a3SShuo Chen#include <assert.h> 1465c497a3SShuo Chen#include <poll.h> 1565c497a3SShuo Chen 1665c497a3SShuo Chenusing namespace muduo; 1765c497a3SShuo Chen 1865c497a3SShuo ChenPoller::Poller(EventLoop* loop) 1965c497a3SShuo Chen : ownerLoop_(loop) 2065c497a3SShuo Chen{ 2165c497a3SShuo Chen} 2265c497a3SShuo Chen 2365c497a3SShuo ChenPoller::~Poller() 2465c497a3SShuo Chen{ 2565c497a3SShuo Chen} 2665c497a3SShuo Chen 2765c497a3SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 2865c497a3SShuo Chen{ 2965c497a3SShuo Chen // XXX pollfds_ shouldn't change 3065c497a3SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 3165c497a3SShuo Chen Timestamp now(Timestamp::now()); 32b4a5ce52SShuo Chen if (numEvents > 0) { 3365c497a3SShuo Chen LOG_TRACE << numEvents << " events happended"; 3465c497a3SShuo Chen fillActiveChannels(numEvents, activeChannels); 35b4a5ce52SShuo Chen } else if (numEvents == 0) { 3665c497a3SShuo Chen LOG_TRACE << " nothing happended"; 37b4a5ce52SShuo Chen } else { 3865c497a3SShuo Chen LOG_SYSERR << "Poller::poll()"; 3965c497a3SShuo Chen } 4065c497a3SShuo Chen return now; 4165c497a3SShuo Chen} 4265c497a3SShuo Chen 4365c497a3SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 4465c497a3SShuo Chen ChannelList* activeChannels) const 4565c497a3SShuo Chen{ 4665c497a3SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 4765c497a3SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 4865c497a3SShuo Chen { 4965c497a3SShuo Chen if (pfd->revents > 0) 5065c497a3SShuo Chen { 5165c497a3SShuo Chen --numEvents; 5265c497a3SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 5365c497a3SShuo Chen assert(ch != channels_.end()); 5465c497a3SShuo Chen Channel* channel = ch->second; 5565c497a3SShuo Chen assert(channel->fd() == pfd->fd); 5665c497a3SShuo Chen channel->set_revents(pfd->revents); 5765c497a3SShuo Chen // pfd->revents = 0; 5865c497a3SShuo Chen activeChannels->push_back(channel); 5965c497a3SShuo Chen } 6065c497a3SShuo Chen } 6165c497a3SShuo Chen} 6265c497a3SShuo Chen 6365c497a3SShuo Chenvoid Poller::updateChannel(Channel* channel) 6465c497a3SShuo Chen{ 6565c497a3SShuo Chen assertInLoopThread(); 6665c497a3SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67b4a5ce52SShuo Chen if (channel->index() < 0) { 6865c497a3SShuo Chen // a new one, add to pollfds_ 6965c497a3SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 7065c497a3SShuo Chen struct pollfd pfd; 7165c497a3SShuo Chen pfd.fd = channel->fd(); 7265c497a3SShuo Chen pfd.events = static_cast<short>(channel->events()); 7365c497a3SShuo Chen pfd.revents = 0; 7465c497a3SShuo Chen pollfds_.push_back(pfd); 7565c497a3SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 7665c497a3SShuo Chen channel->set_index(idx); 7765c497a3SShuo Chen channels_[pfd.fd] = channel; 78b4a5ce52SShuo Chen } else { 7965c497a3SShuo Chen // update existing one 8065c497a3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 8165c497a3SShuo Chen assert(channels_[channel->fd()] == channel); 8265c497a3SShuo Chen int idx = channel->index(); 8365c497a3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 8465c497a3SShuo Chen struct pollfd& pfd = pollfds_[idx]; 8565c497a3SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 8665c497a3SShuo Chen pfd.events = static_cast<short>(channel->events()); 8765c497a3SShuo Chen pfd.revents = 0; 88b4a5ce52SShuo Chen if (channel->isNoneEvent()) { 8965c497a3SShuo Chen // ignore this pollfd 9065c497a3SShuo Chen pfd.fd = -channel->fd()-1; 9165c497a3SShuo Chen } 9265c497a3SShuo Chen } 9365c497a3SShuo Chen} 9465c497a3SShuo Chen 9565c497a3SShuo Chenvoid Poller::removeChannel(Channel* channel) 9665c497a3SShuo Chen{ 9765c497a3SShuo Chen assertInLoopThread(); 9865c497a3SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 9965c497a3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 10065c497a3SShuo Chen assert(channels_[channel->fd()] == channel); 10165c497a3SShuo Chen assert(channel->isNoneEvent()); 10265c497a3SShuo Chen int idx = channel->index(); 10365c497a3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 10465c497a3SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 10565c497a3SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 10665c497a3SShuo Chen size_t n = channels_.erase(channel->fd()); 10765c497a3SShuo Chen assert(n == 1); (void)n; 108b4a5ce52SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 10965c497a3SShuo Chen pollfds_.pop_back(); 110b4a5ce52SShuo Chen } else { 11165c497a3SShuo Chen int channelAtEnd = pollfds_.back().fd; 11265c497a3SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113b4a5ce52SShuo Chen if (channelAtEnd < 0) { 11465c497a3SShuo Chen channelAtEnd = -channelAtEnd-1; 11565c497a3SShuo Chen } 11665c497a3SShuo Chen channels_[channelAtEnd]->set_index(idx); 11765c497a3SShuo Chen pollfds_.pop_back(); 11865c497a3SShuo Chen } 11965c497a3SShuo Chen} 12065c497a3SShuo Chen 121