Poller.cc revision 2a18e699
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()); 322a18e699SShuo Chen if (numEvents > 0) 332a18e699SShuo Chen { 342a18e699SShuo Chen LOG_TRACE << numEvents << " events happended"; 352a18e699SShuo Chen fillActiveChannels(numEvents, activeChannels); 362a18e699SShuo Chen } 372a18e699SShuo Chen else if (numEvents == 0) 382a18e699SShuo Chen { 392a18e699SShuo Chen LOG_TRACE << " nothing happended"; 402a18e699SShuo Chen } 412a18e699SShuo Chen else 422a18e699SShuo Chen { 432a18e699SShuo Chen LOG_SYSERR << "Poller::poll()"; 442a18e699SShuo Chen } 452a18e699SShuo Chen return now; 462a18e699SShuo Chen} 472a18e699SShuo Chen 482a18e699SShuo Chenvoid Poller::fillActiveChannels(int numEvents, 492a18e699SShuo Chen ChannelList* activeChannels) const 502a18e699SShuo Chen{ 512a18e699SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 522a18e699SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 532a18e699SShuo Chen { 542a18e699SShuo Chen if (pfd->revents > 0) 552a18e699SShuo Chen { 562a18e699SShuo Chen --numEvents; 572a18e699SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 582a18e699SShuo Chen assert(ch != channels_.end()); 592a18e699SShuo Chen Channel* channel = ch->second; 602a18e699SShuo Chen assert(channel->fd() == pfd->fd); 612a18e699SShuo Chen channel->set_revents(pfd->revents); 622a18e699SShuo Chen // pfd->revents = 0; 632a18e699SShuo Chen activeChannels->push_back(channel); 642a18e699SShuo Chen } 652a18e699SShuo Chen } 662a18e699SShuo Chen} 672a18e699SShuo Chen 682a18e699SShuo Chenvoid Poller::updateChannel(Channel* channel) 692a18e699SShuo Chen{ 702a18e699SShuo Chen assertInLoopThread(); 712a18e699SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 722a18e699SShuo Chen if (channel->index() < 0) 732a18e699SShuo Chen { 742a18e699SShuo Chen // a new one, add to pollfds_ 752a18e699SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 762a18e699SShuo Chen struct pollfd pfd; 772a18e699SShuo Chen pfd.fd = channel->fd(); 782a18e699SShuo Chen pfd.events = static_cast<short>(channel->events()); 792a18e699SShuo Chen pfd.revents = 0; 802a18e699SShuo Chen pollfds_.push_back(pfd); 812a18e699SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 822a18e699SShuo Chen channel->set_index(idx); 832a18e699SShuo Chen channels_[pfd.fd] = channel; 842a18e699SShuo Chen } 852a18e699SShuo Chen else 862a18e699SShuo Chen { 872a18e699SShuo Chen // update existing one 882a18e699SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 892a18e699SShuo Chen assert(channels_[channel->fd()] == channel); 902a18e699SShuo Chen int idx = channel->index(); 912a18e699SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 922a18e699SShuo Chen struct pollfd& pfd = pollfds_[idx]; 932a18e699SShuo Chen assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 942a18e699SShuo Chen pfd.events = static_cast<short>(channel->events()); 952a18e699SShuo Chen pfd.revents = 0; 962a18e699SShuo Chen if (channel->isNoneEvent()) 972a18e699SShuo Chen { 982a18e699SShuo Chen // ignore this pollfd 992a18e699SShuo Chen pfd.fd = -channel->fd()-1; 1002a18e699SShuo Chen } 1012a18e699SShuo Chen } 1022a18e699SShuo Chen} 1032a18e699SShuo Chen 1042a18e699SShuo Chenvoid Poller::removeChannel(Channel* channel) 1052a18e699SShuo Chen{ 1062a18e699SShuo Chen assertInLoopThread(); 1072a18e699SShuo Chen LOG_TRACE << "fd = " << channel->fd(); 1082a18e699SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 1092a18e699SShuo Chen assert(channels_[channel->fd()] == channel); 1102a18e699SShuo Chen assert(channel->isNoneEvent()); 1112a18e699SShuo Chen int idx = channel->index(); 1122a18e699SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 1132a18e699SShuo Chen const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 1142a18e699SShuo Chen assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 1152a18e699SShuo Chen size_t n = channels_.erase(channel->fd()); 1162a18e699SShuo Chen assert(n == 1); (void)n; 1172a18e699SShuo Chen if (implicit_cast<size_t>(idx) == pollfds_.size()-1) 1182a18e699SShuo Chen { 1192a18e699SShuo Chen pollfds_.pop_back(); 1202a18e699SShuo Chen } 1212a18e699SShuo Chen else 1222a18e699SShuo Chen { 1232a18e699SShuo Chen int channelAtEnd = pollfds_.back().fd; 1242a18e699SShuo Chen iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 1252a18e699SShuo Chen if (channelAtEnd < 0) 1262a18e699SShuo Chen { 1272a18e699SShuo Chen channelAtEnd = -channelAtEnd-1; 1282a18e699SShuo Chen } 1292a18e699SShuo Chen channels_[channelAtEnd]->set_index(idx); 1302a18e699SShuo Chen pollfds_.pop_back(); 1312a18e699SShuo Chen } 1322a18e699SShuo Chen} 1332a18e699SShuo Chen 134