1 // excerpts from http://code.google.com/p/muduo/ 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the License file. 5 // 6 // Author: Shuo Chen (chenshuo at chenshuo dot com) 7 8 #include "Poller.h" 9 10 #include "Channel.h" 11 #include "logging/Logging.h" 12 13 #include <assert.h> 14 #include <poll.h> 15 16 using namespace muduo; 17 18 Poller::Poller(EventLoop* loop) 19 : ownerLoop_(loop) 20 { 21 } 22 23 Poller::~Poller() 24 { 25 } 26 27 Timestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 28 { 29 // XXX pollfds_ shouldn't change 30 int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 31 Timestamp now(Timestamp::now()); 32 if (numEvents > 0) { 33 LOG_TRACE << numEvents << " events happended"; 34 fillActiveChannels(numEvents, activeChannels); 35 } else if (numEvents == 0) { 36 LOG_TRACE << " nothing happended"; 37 } else { 38 LOG_SYSERR << "Poller::poll()"; 39 } 40 return now; 41 } 42 43 void Poller::fillActiveChannels(int numEvents, 44 ChannelList* activeChannels) const 45 { 46 for (PollFdList::const_iterator pfd = pollfds_.begin(); 47 pfd != pollfds_.end() && numEvents > 0; ++pfd) 48 { 49 if (pfd->revents > 0) 50 { 51 --numEvents; 52 ChannelMap::const_iterator ch = channels_.find(pfd->fd); 53 assert(ch != channels_.end()); 54 Channel* channel = ch->second; 55 assert(channel->fd() == pfd->fd); 56 channel->set_revents(pfd->revents); 57 // pfd->revents = 0; 58 activeChannels->push_back(channel); 59 } 60 } 61 } 62 63 void Poller::updateChannel(Channel* channel) 64 { 65 assertInLoopThread(); 66 LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67 if (channel->index() < 0) { 68 // a new one, add to pollfds_ 69 assert(channels_.find(channel->fd()) == channels_.end()); 70 struct pollfd pfd; 71 pfd.fd = channel->fd(); 72 pfd.events = static_cast<short>(channel->events()); 73 pfd.revents = 0; 74 pollfds_.push_back(pfd); 75 int idx = static_cast<int>(pollfds_.size())-1; 76 channel->set_index(idx); 77 channels_[pfd.fd] = channel; 78 } else { 79 // update existing one 80 assert(channels_.find(channel->fd()) != channels_.end()); 81 assert(channels_[channel->fd()] == channel); 82 int idx = channel->index(); 83 assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 84 struct pollfd& pfd = pollfds_[idx]; 85! assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 86 pfd.events = static_cast<short>(channel->events()); 87 pfd.revents = 0; 88 if (channel->isNoneEvent()) { 89 // ignore this pollfd 90! pfd.fd = -channel->fd()-1; 91 } 92 } 93 } 94 95+void Poller::removeChannel(Channel* channel) 96+{ 97+ assertInLoopThread(); 98+ LOG_TRACE << "fd = " << channel->fd(); 99+ assert(channels_.find(channel->fd()) != channels_.end()); 100+ assert(channels_[channel->fd()] == channel); 101+ assert(channel->isNoneEvent()); 102+ int idx = channel->index(); 103+ assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 104+ const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 105+ assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 106+ size_t n = channels_.erase(channel->fd()); 107+ assert(n == 1); (void)n; 108+ if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 109+ pollfds_.pop_back(); 110+ } else { 111+ int channelAtEnd = pollfds_.back().fd; 112+ iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113+ if (channelAtEnd < 0) { 114+ channelAtEnd = -channelAtEnd-1; 115+ } 116+ channels_[channelAtEnd]->set_index(idx); 117+ pollfds_.pop_back(); 118+ } 119+} 120+ 121