12a18e699SShuo Chen// excerpts from http://code.google.com/p/muduo/ 22a18e699SShuo Chen// 32a18e699SShuo Chen// Use of this source code is governed by a BSD-style license 42a18e699SShuo Chen// that can be found in the License file. 52a18e699SShuo Chen// 62a18e699SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 72a18e699SShuo Chen 82a18e699SShuo Chen#include "Poller.h" 92a18e699SShuo Chen 102a18e699SShuo Chen#include "Channel.h" 112a18e699SShuo Chen#include "logging/Logging.h" 122a18e699SShuo Chen 132a18e699SShuo Chen#include <assert.h> 142a18e699SShuo Chen#include <poll.h> 152a18e699SShuo Chen 162a18e699SShuo Chenusing namespace muduo; 172a18e699SShuo Chen 182a18e699SShuo ChenPoller::Poller(EventLoop* loop) 192a18e699SShuo Chen : ownerLoop_(loop) 202a18e699SShuo Chen{ 212a18e699SShuo Chen} 222a18e699SShuo Chen 232a18e699SShuo ChenPoller::~Poller() 242a18e699SShuo Chen{ 252a18e699SShuo Chen} 262a18e699SShuo Chen 272a18e699SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 282a18e699SShuo Chen{ 292a18e699SShuo Chen // XXX pollfds_ shouldn't change 302a18e699SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 312a18e699SShuo Chen Timestamp now(Timestamp::now()); 32b4a5ce52SShuo Chen if (numEvents > 0) { 332a18e699SShuo Chen LOG_TRACE << numEvents << " events happended"; 342a18e699SShuo Chen fillActiveChannels(numEvents, activeChannels); 35b4a5ce52SShuo Chen } else if (numEvents == 0) { 362a18e699SShuo Chen LOG_TRACE << " nothing happended"; 37b4a5ce52SShuo Chen } else { 382a18e699SShuo Chen LOG_SYSERR << "Poller::poll()"; 392a18e699SShuo Chen } 402a18e699SShuo Chen return now; 412a18e699SShuo Chen} 422a18e699SShuo Chen 432a18e699SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 442a18e699SShuo Chen ChannelList* activeChannels) const 452a18e699SShuo Chen{ 462a18e699SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 472a18e699SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 482a18e699SShuo Chen { 492a18e699SShuo Chen if (pfd->revents > 0) 502a18e699SShuo Chen { 512a18e699SShuo Chen --numEvents; 522a18e699SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 532a18e699SShuo Chen assert(ch != channels_.end()); 542a18e699SShuo Chen Channel* channel = ch->second; 552a18e699SShuo Chen assert(channel->fd() == pfd->fd); 562a18e699SShuo Chen channel->set_revents(pfd->revents); 572a18e699SShuo Chen // pfd->revents = 0; 582a18e699SShuo Chen activeChannels->push_back(channel); 592a18e699SShuo Chen } 602a18e699SShuo Chen } 612a18e699SShuo Chen} 622a18e699SShuo Chen 632a18e699SShuo Chenvoid Poller::updateChannel(Channel* channel) 642a18e699SShuo Chen{ 652a18e699SShuo Chen assertInLoopThread(); 662a18e699SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67b4a5ce52SShuo Chen if (channel->index() < 0) { 682a18e699SShuo Chen // a new one, add to pollfds_ 692a18e699SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 702a18e699SShuo Chen struct pollfd pfd; 712a18e699SShuo Chen pfd.fd = channel->fd(); 722a18e699SShuo Chen pfd.events = static_cast<short>(channel->events()); 732a18e699SShuo Chen pfd.revents = 0; 742a18e699SShuo Chen pollfds_.push_back(pfd); 752a18e699SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 762a18e699SShuo Chen channel->set_index(idx); 772a18e699SShuo Chen channels_[pfd.fd] = channel; 78b4a5ce52SShuo Chen } else { 792a18e699SShuo Chen // update existing one 802a18e699SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 812a18e699SShuo Chen assert(channels_[channel->fd()] == channel); 822a18e699SShuo Chen int idx = channel->index(); 832a18e699SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 842a18e699SShuo Chen struct pollfd& pfd = pollfds_[idx]; 852a18e699SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 862a18e699SShuo Chen pfd.events = static_cast<short>(channel->events()); 872a18e699SShuo Chen pfd.revents = 0; 88b4a5ce52SShuo Chen if (channel->isNoneEvent()) { 892a18e699SShuo Chen // ignore this pollfd 902a18e699SShuo Chen pfd.fd = -channel->fd()-1; 912a18e699SShuo Chen } 922a18e699SShuo Chen } 932a18e699SShuo Chen} 942a18e699SShuo Chen 952a18e699SShuo Chenvoid Poller::removeChannel(Channel* channel) 962a18e699SShuo Chen{ 972a18e699SShuo Chen assertInLoopThread(); 982a18e699SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 992a18e699SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 1002a18e699SShuo Chen assert(channels_[channel->fd()] == channel); 1012a18e699SShuo Chen assert(channel->isNoneEvent()); 1022a18e699SShuo Chen int idx = channel->index(); 1032a18e699SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 1042a18e699SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 1052a18e699SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 1062a18e699SShuo Chen size_t n = channels_.erase(channel->fd()); 1072a18e699SShuo Chen assert(n == 1); (void)n; 108b4a5ce52SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 1092a18e699SShuo Chen pollfds_.pop_back(); 110b4a5ce52SShuo Chen } else { 1112a18e699SShuo Chen int channelAtEnd = pollfds_.back().fd; 1122a18e699SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113b4a5ce52SShuo Chen if (channelAtEnd < 0) { 1142a18e699SShuo Chen channelAtEnd = -channelAtEnd-1; 1152a18e699SShuo Chen } 1162a18e699SShuo Chen channels_[channelAtEnd]->set_index(idx); 1172a18e699SShuo Chen pollfds_.pop_back(); 1182a18e699SShuo Chen } 1192a18e699SShuo Chen} 1202a18e699SShuo Chen 121