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()); 32b4a5ce52SShuo Chen if (numEvents > 0) { 33048f6023SShuo Chen LOG_TRACE << numEvents << " events happended"; 34048f6023SShuo Chen fillActiveChannels(numEvents, activeChannels); 35b4a5ce52SShuo Chen } else if (numEvents == 0) { 36048f6023SShuo Chen LOG_TRACE << " nothing happended"; 37b4a5ce52SShuo Chen } else { 38048f6023SShuo Chen LOG_SYSERR << "Poller::poll()"; 39048f6023SShuo Chen } 40048f6023SShuo Chen return now; 41048f6023SShuo Chen } 42048f6023SShuo Chen 43048f6023SShuo Chen void Poller::fillActiveChannels(int numEvents, 44048f6023SShuo Chen ChannelList* activeChannels) const 45048f6023SShuo Chen { 46048f6023SShuo Chen for (PollFdList::const_iterator pfd = pollfds_.begin(); 47048f6023SShuo Chen pfd != pollfds_.end() && numEvents > 0; ++pfd) 48048f6023SShuo Chen { 49048f6023SShuo Chen if (pfd->revents > 0) 50048f6023SShuo Chen { 51048f6023SShuo Chen --numEvents; 52048f6023SShuo Chen ChannelMap::const_iterator ch = channels_.find(pfd->fd); 53048f6023SShuo Chen assert(ch != channels_.end()); 54048f6023SShuo Chen Channel* channel = ch->second; 55048f6023SShuo Chen assert(channel->fd() == pfd->fd); 56048f6023SShuo Chen channel->set_revents(pfd->revents); 57048f6023SShuo Chen // pfd->revents = 0; 58048f6023SShuo Chen activeChannels->push_back(channel); 59048f6023SShuo Chen } 60048f6023SShuo Chen } 61048f6023SShuo Chen } 62048f6023SShuo Chen 63048f6023SShuo Chen void Poller::updateChannel(Channel* channel) 64048f6023SShuo Chen { 65048f6023SShuo Chen assertInLoopThread(); 66048f6023SShuo Chen LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events(); 67b4a5ce52SShuo Chen if (channel->index() < 0) { 68048f6023SShuo Chen // a new one, add to pollfds_ 69048f6023SShuo Chen assert(channels_.find(channel->fd()) == channels_.end()); 70048f6023SShuo Chen struct pollfd pfd; 71048f6023SShuo Chen pfd.fd = channel->fd(); 72048f6023SShuo Chen pfd.events = static_cast<short>(channel->events()); 73048f6023SShuo Chen pfd.revents = 0; 74048f6023SShuo Chen pollfds_.push_back(pfd); 75048f6023SShuo Chen int idx = static_cast<int>(pollfds_.size())-1; 76048f6023SShuo Chen channel->set_index(idx); 77048f6023SShuo Chen channels_[pfd.fd] = channel; 78b4a5ce52SShuo Chen } else { 79048f6023SShuo Chen // update existing one 80048f6023SShuo Chen assert(channels_.find(channel->fd()) != channels_.end()); 81048f6023SShuo Chen assert(channels_[channel->fd()] == channel); 82048f6023SShuo Chen int idx = channel->index(); 83048f6023SShuo Chen assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 84048f6023SShuo Chen struct pollfd& pfd = pollfds_[idx]; 85048f6023SShuo Chen! assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1); 86048f6023SShuo Chen pfd.events = static_cast<short>(channel->events()); 87048f6023SShuo Chen pfd.revents = 0; 88b4a5ce52SShuo Chen if (channel->isNoneEvent()) { 89048f6023SShuo Chen // ignore this pollfd 90048f6023SShuo Chen! pfd.fd = -channel->fd()-1; 91048f6023SShuo Chen } 92048f6023SShuo Chen } 93048f6023SShuo Chen } 94048f6023SShuo Chen 95048f6023SShuo Chen+void Poller::removeChannel(Channel* channel) 96048f6023SShuo Chen+{ 97048f6023SShuo Chen+ assertInLoopThread(); 98048f6023SShuo Chen+ LOG_TRACE << "fd = " << channel->fd(); 99048f6023SShuo Chen+ assert(channels_.find(channel->fd()) != channels_.end()); 100048f6023SShuo Chen+ assert(channels_[channel->fd()] == channel); 101048f6023SShuo Chen+ assert(channel->isNoneEvent()); 102048f6023SShuo Chen+ int idx = channel->index(); 103048f6023SShuo Chen+ assert(0 <= idx && idx < static_cast<int>(pollfds_.size())); 104048f6023SShuo Chen+ const struct pollfd& pfd = pollfds_[idx]; (void)pfd; 105048f6023SShuo Chen+ assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events()); 106048f6023SShuo Chen+ size_t n = channels_.erase(channel->fd()); 107048f6023SShuo Chen+ assert(n == 1); (void)n; 108b4a5ce52SShuo Chen+ if (implicit_cast<size_t>(idx) == pollfds_.size()-1) { 109048f6023SShuo Chen+ pollfds_.pop_back(); 110b4a5ce52SShuo Chen+ } else { 111048f6023SShuo Chen+ int channelAtEnd = pollfds_.back().fd; 112048f6023SShuo Chen+ iter_swap(pollfds_.begin()+idx, pollfds_.end()-1); 113b4a5ce52SShuo Chen+ if (channelAtEnd < 0) { 114048f6023SShuo Chen+ channelAtEnd = -channelAtEnd-1; 115048f6023SShuo Chen+ } 116048f6023SShuo Chen+ channels_[channelAtEnd]->set_index(idx); 117048f6023SShuo Chen+ pollfds_.pop_back(); 118048f6023SShuo Chen+ } 119048f6023SShuo Chen+} 120048f6023SShuo Chen+ 121