Poller.cc revision 65c497a3
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()); 3265c497a3SShuo Chen if (numEvents > 0) 3365c497a3SShuo Chen { 3465c497a3SShuo Chen LOG_TRACE << numEvents << " events happended"; 3565c497a3SShuo Chen fillActiveChannels(numEvents, activeChannels); 3665c497a3SShuo Chen } 3765c497a3SShuo Chen else if (numEvents == 0) 3865c497a3SShuo Chen { 3965c497a3SShuo Chen LOG_TRACE << " nothing happended"; 4065c497a3SShuo Chen } 4165c497a3SShuo Chen else 4265c497a3SShuo Chen { 4365c497a3SShuo Chen LOG_SYSERR << "Poller::poll()"; 4465c497a3SShuo Chen } 4565c497a3SShuo Chen return now; 4665c497a3SShuo Chen} 4765c497a3SShuo Chen 4865c497a3SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 4965c497a3SShuo Chen ChannelList* activeChannels) const 5065c497a3SShuo Chen{ 5165c497a3SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 5265c497a3SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 5365c497a3SShuo Chen { 5465c497a3SShuo Chen if (pfd->revents > 0) 5565c497a3SShuo Chen { 5665c497a3SShuo Chen --numEvents; 5765c497a3SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 5865c497a3SShuo Chen assert(ch != channels_.end()); 5965c497a3SShuo Chen Channel* channel = ch->second; 6065c497a3SShuo Chen assert(channel->fd() == pfd->fd); 6165c497a3SShuo Chen channel->set_revents(pfd->revents); 6265c497a3SShuo Chen // pfd->revents = 0; 6365c497a3SShuo Chen activeChannels->push_back(channel); 6465c497a3SShuo Chen } 6565c497a3SShuo Chen } 6665c497a3SShuo Chen} 6765c497a3SShuo Chen 6865c497a3SShuo Chenvoid Poller::updateChannel(Channel* channel) 6965c497a3SShuo Chen{ 7065c497a3SShuo Chen assertInLoopThread(); 7165c497a3SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 7265c497a3SShuo Chen if (channel->index() < 0) 7365c497a3SShuo Chen { 7465c497a3SShuo Chen // a new one, add to pollfds_ 7565c497a3SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 7665c497a3SShuo Chen struct pollfd pfd; 7765c497a3SShuo Chen pfd.fd = channel->fd(); 7865c497a3SShuo Chen pfd.events = static_cast<short>(channel->events()); 7965c497a3SShuo Chen pfd.revents = 0; 8065c497a3SShuo Chen pollfds_.push_back(pfd); 8165c497a3SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 8265c497a3SShuo Chen channel->set_index(idx); 8365c497a3SShuo Chen channels_[pfd.fd] = channel; 8465c497a3SShuo Chen } 8565c497a3SShuo Chen else 8665c497a3SShuo Chen { 8765c497a3SShuo Chen // update existing one 8865c497a3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 8965c497a3SShuo Chen assert(channels_[channel->fd()] == channel); 9065c497a3SShuo Chen int idx = channel->index(); 9165c497a3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 9265c497a3SShuo Chen struct pollfd& pfd = pollfds_[idx]; 9365c497a3SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 9465c497a3SShuo Chen pfd.events = static_cast<short>(channel->events()); 9565c497a3SShuo Chen pfd.revents = 0; 9665c497a3SShuo Chen if (channel->isNoneEvent()) 9765c497a3SShuo Chen { 9865c497a3SShuo Chen // ignore this pollfd 9965c497a3SShuo Chen pfd.fd = -channel->fd()-1; 10065c497a3SShuo Chen } 10165c497a3SShuo Chen } 10265c497a3SShuo Chen} 10365c497a3SShuo Chen 10465c497a3SShuo Chenvoid Poller::removeChannel(Channel* channel) 10565c497a3SShuo Chen{ 10665c497a3SShuo Chen assertInLoopThread(); 10765c497a3SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 10865c497a3SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 10965c497a3SShuo Chen assert(channels_[channel->fd()] == channel); 11065c497a3SShuo Chen assert(channel->isNoneEvent()); 11165c497a3SShuo Chen int idx = channel->index(); 11265c497a3SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 11365c497a3SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 11465c497a3SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 11565c497a3SShuo Chen size_t n = channels_.erase(channel->fd()); 11665c497a3SShuo Chen assert(n == 1); (void)n; 11765c497a3SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) 11865c497a3SShuo Chen { 11965c497a3SShuo Chen pollfds_.pop_back(); 12065c497a3SShuo Chen } 12165c497a3SShuo Chen else 12265c497a3SShuo Chen { 12365c497a3SShuo Chen int channelAtEnd = pollfds_.back().fd; 12465c497a3SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 12565c497a3SShuo Chen if (channelAtEnd < 0) 12665c497a3SShuo Chen { 12765c497a3SShuo Chen channelAtEnd = -channelAtEnd-1; 12865c497a3SShuo Chen } 12965c497a3SShuo Chen channels_[channelAtEnd]->set_index(idx); 13065c497a3SShuo Chen pollfds_.pop_back(); 13165c497a3SShuo Chen } 13265c497a3SShuo Chen} 13365c497a3SShuo Chen 134