s06-s05-Poller.cc.diff revision 048f6023
1048f6023SShuo Chen // excerpts from http://code.google.com/p/muduo/ 2048f6023SShuo Chen // 3048f6023SShuo Chen // Use of this source code is governed by a BSD-style license 4048f6023SShuo Chen // that can be found in the License file. 5048f6023SShuo Chen // 6048f6023SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com) 7048f6023SShuo Chen 8048f6023SShuo Chen #include "Poller.h" 9048f6023SShuo Chen 10048f6023SShuo Chen #include "Channel.h" 11048f6023SShuo Chen #include "logging/Logging.h" 12048f6023SShuo Chen 13048f6023SShuo Chen #include <assert.h> 14048f6023SShuo Chen #include <poll.h> 15048f6023SShuo Chen 16048f6023SShuo Chen using namespace muduo; 17048f6023SShuo Chen 18048f6023SShuo Chen Poller::Poller(EventLoop* loop) 19048f6023SShuo Chen : ownerLoop_(loop) 20048f6023SShuo Chen { 21048f6023SShuo Chen } 22048f6023SShuo Chen 23048f6023SShuo Chen Poller::~Poller() 24048f6023SShuo Chen { 25048f6023SShuo Chen } 26048f6023SShuo Chen 27048f6023SShuo Chen Timestamp Poller::poll(int timeoutMs, ChannelList* activeChannels) 28048f6023SShuo Chen { 29048f6023SShuo Chen // XXX pollfds_ shouldn't change 30048f6023SShuo Chen int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs); 31048f6023SShuo Chen Timestamp now(Timestamp::now()); 32048f6023SShuo Chen if (numEvents > 0) 33048f6023SShuo Chen { 34048f6023SShuo Chen LOG_TRACE << numEvents << " events happended"; 35048f6023SShuo Chen fillActiveChannels(numEvents, activeChannels); 36048f6023SShuo Chen } 37048f6023SShuo Chen else if (numEvents == 0) 38048f6023SShuo Chen { 39048f6023SShuo Chen LOG_TRACE << " nothing happended"; 40048f6023SShuo Chen } 41048f6023SShuo Chen else 42048f6023SShuo Chen { 43048f6023SShuo Chen LOG_SYSERR << "Poller::poll()"; 44048f6023SShuo Chen } 45048f6023SShuo Chen return now; 46048f6023SShuo Chen } 47048f6023SShuo Chen 48048f6023SShuo Chen void Poller::fillActiveChannels(int numEvents, 49048f6023SShuo Chen ChannelList* activeChannels) const 50048f6023SShuo Chen { 51048f6023SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 52048f6023SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 53048f6023SShuo Chen { 54048f6023SShuo Chen if (pfd->revents > 0) 55048f6023SShuo Chen { 56048f6023SShuo Chen --numEvents; 57048f6023SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 58048f6023SShuo Chen assert(ch != channels_.end()); 59048f6023SShuo Chen Channel* channel = ch->second; 60048f6023SShuo Chen assert(channel->fd() == pfd->fd); 61048f6023SShuo Chen channel->set_revents(pfd->revents); 62048f6023SShuo Chen // pfd->revents = 0; 63048f6023SShuo Chen activeChannels->push_back(channel); 64048f6023SShuo Chen } 65048f6023SShuo Chen } 66048f6023SShuo Chen } 67048f6023SShuo Chen 68048f6023SShuo Chen void Poller::updateChannel(Channel* channel) 69048f6023SShuo Chen { 70048f6023SShuo Chen assertInLoopThread(); 71048f6023SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 72048f6023SShuo Chen if (channel->index() < 0) 73048f6023SShuo Chen { 74048f6023SShuo Chen // a new one, add to pollfds_ 75048f6023SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 76048f6023SShuo Chen struct pollfd pfd; 77048f6023SShuo Chen pfd.fd = channel->fd(); 78048f6023SShuo Chen pfd.events = static_cast<short>(channel->events()); 79048f6023SShuo Chen pfd.revents = 0; 80048f6023SShuo Chen pollfds_.push_back(pfd); 81048f6023SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 82048f6023SShuo Chen channel->set_index(idx); 83048f6023SShuo Chen channels_[pfd.fd] = channel; 84048f6023SShuo Chen } 85048f6023SShuo Chen else 86048f6023SShuo Chen { 87048f6023SShuo Chen // update existing one 88048f6023SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 89048f6023SShuo Chen assert(channels_[channel->fd()] == channel); 90048f6023SShuo Chen int idx = channel->index(); 91048f6023SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 92048f6023SShuo Chen struct pollfd& pfd = pollfds_[idx]; 93048f6023SShuo Chen! assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 94048f6023SShuo Chen pfd.events = static_cast<short>(channel->events()); 95048f6023SShuo Chen pfd.revents = 0; 96048f6023SShuo Chen if (channel->isNoneEvent()) 97048f6023SShuo Chen { 98048f6023SShuo Chen // ignore this pollfd 99048f6023SShuo Chen! pfd.fd = -channel->fd()-1; 100048f6023SShuo Chen } 101048f6023SShuo Chen } 102048f6023SShuo Chen } 103048f6023SShuo Chen 104048f6023SShuo Chen+void Poller::removeChannel(Channel* channel) 105048f6023SShuo Chen+{ 106048f6023SShuo Chen+ assertInLoopThread(); 107048f6023SShuo Chen+ LOG_TRACE << "fd = " << channel->fd(); 108048f6023SShuo Chen+ assert(channels_.find(channel->fd()) != channels_.end()); 109048f6023SShuo Chen+ assert(channels_[channel->fd()] == channel); 110048f6023SShuo Chen+ assert(channel->isNoneEvent()); 111048f6023SShuo Chen+ int idx = channel->index(); 112048f6023SShuo Chen+ assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 113048f6023SShuo Chen+ const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 114048f6023SShuo Chen+ assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 115048f6023SShuo Chen+ size_t n = channels_.erase(channel->fd()); 116048f6023SShuo Chen+ assert(n == 1); (void)n; 117048f6023SShuo Chen+ if (implicit_cast<size_t>(idx) == pollfds_.size()-1) 118048f6023SShuo Chen+ { 119048f6023SShuo Chen+ pollfds_.pop_back(); 120048f6023SShuo Chen+ } 121048f6023SShuo Chen+ else 122048f6023SShuo Chen+ { 123048f6023SShuo Chen+ int channelAtEnd = pollfds_.back().fd; 124048f6023SShuo Chen+ iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 125048f6023SShuo Chen+ if (channelAtEnd < 0) 126048f6023SShuo Chen+ { 127048f6023SShuo Chen+ channelAtEnd = -channelAtEnd-1; 128048f6023SShuo Chen+ } 129048f6023SShuo Chen+ channels_[channelAtEnd]->set_index(idx); 130048f6023SShuo Chen+ pollfds_.pop_back(); 131048f6023SShuo Chen+ } 132048f6023SShuo Chen+} 133048f6023SShuo Chen+ 134