14b7a333eSShuo Chen// excerpts from http://code.google.com/p/muduo/
24b7a333eSShuo Chen//
34b7a333eSShuo Chen// Use of this source code is governed by a BSD-style license
44b7a333eSShuo Chen// that can be found in the License file.
54b7a333eSShuo Chen//
64b7a333eSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
74b7a333eSShuo Chen
84b7a333eSShuo Chen#include "Poller.h"
94b7a333eSShuo Chen
104b7a333eSShuo Chen#include "Channel.h"
114b7a333eSShuo Chen#include "logging/Logging.h"
124b7a333eSShuo Chen
134b7a333eSShuo Chen#include <assert.h>
144b7a333eSShuo Chen#include <poll.h>
154b7a333eSShuo Chen
164b7a333eSShuo Chenusing namespace muduo;
174b7a333eSShuo Chen
184b7a333eSShuo ChenPoller::Poller(EventLoop* loop)
194b7a333eSShuo Chen  : ownerLoop_(loop)
204b7a333eSShuo Chen{
214b7a333eSShuo Chen}
224b7a333eSShuo Chen
234b7a333eSShuo ChenPoller::~Poller()
244b7a333eSShuo Chen{
254b7a333eSShuo Chen}
264b7a333eSShuo Chen
274b7a333eSShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
284b7a333eSShuo Chen{
294b7a333eSShuo Chen  // XXX pollfds_ shouldn't change
304b7a333eSShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
314b7a333eSShuo Chen  Timestamp now(Timestamp::now());
32b4a5ce52SShuo Chen  if (numEvents > 0) {
334b7a333eSShuo Chen    LOG_TRACE << numEvents << " events happended";
344b7a333eSShuo Chen    fillActiveChannels(numEvents, activeChannels);
35b4a5ce52SShuo Chen  } else if (numEvents == 0) {
364b7a333eSShuo Chen    LOG_TRACE << " nothing happended";
37b4a5ce52SShuo Chen  } else {
384b7a333eSShuo Chen    LOG_SYSERR << "Poller::poll()";
394b7a333eSShuo Chen  }
404b7a333eSShuo Chen  return now;
414b7a333eSShuo Chen}
424b7a333eSShuo Chen
434b7a333eSShuo Chenvoid Poller::fillActiveChannels(int numEvents,
444b7a333eSShuo Chen                                ChannelList* activeChannels) const
454b7a333eSShuo Chen{
464b7a333eSShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
474b7a333eSShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
484b7a333eSShuo Chen  {
494b7a333eSShuo Chen    if (pfd->revents > 0)
504b7a333eSShuo Chen    {
514b7a333eSShuo Chen      --numEvents;
524b7a333eSShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
534b7a333eSShuo Chen      assert(ch != channels_.end());
544b7a333eSShuo Chen      Channel* channel = ch->second;
554b7a333eSShuo Chen      assert(channel->fd() == pfd->fd);
564b7a333eSShuo Chen      channel->set_revents(pfd->revents);
574b7a333eSShuo Chen      // pfd->revents = 0;
584b7a333eSShuo Chen      activeChannels->push_back(channel);
594b7a333eSShuo Chen    }
604b7a333eSShuo Chen  }
614b7a333eSShuo Chen}
624b7a333eSShuo Chen
634b7a333eSShuo Chenvoid Poller::updateChannel(Channel* channel)
644b7a333eSShuo Chen{
65ee021d99SShuo Chen  assertInLoopThread();
664b7a333eSShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
67b4a5ce52SShuo Chen  if (channel->index() < 0) {
684b7a333eSShuo Chen    // a new one, add to pollfds_
694b7a333eSShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
704b7a333eSShuo Chen    struct pollfd pfd;
714b7a333eSShuo Chen    pfd.fd = channel->fd();
724b7a333eSShuo Chen    pfd.events = static_cast<short>(channel->events());
734b7a333eSShuo Chen    pfd.revents = 0;
744b7a333eSShuo Chen    pollfds_.push_back(pfd);
754b7a333eSShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
764b7a333eSShuo Chen    channel->set_index(idx);
774b7a333eSShuo Chen    channels_[pfd.fd] = channel;
78b4a5ce52SShuo Chen  } else {
794b7a333eSShuo Chen    // update existing one
804b7a333eSShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
814b7a333eSShuo Chen    assert(channels_[channel->fd()] == channel);
824b7a333eSShuo Chen    int idx = channel->index();
834b7a333eSShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
844b7a333eSShuo Chen    struct pollfd& pfd = pollfds_[idx];
854792573fSShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -1);
8617c057c3SShuo Chen    pfd.events = static_cast<short>(channel->events());
8717c057c3SShuo Chen    pfd.revents = 0;
88b4a5ce52SShuo Chen    if (channel->isNoneEvent()) {
894b7a333eSShuo Chen      // ignore this pollfd
904792573fSShuo Chen      pfd.fd = -1;
914b7a333eSShuo Chen    }
924b7a333eSShuo Chen  }
934b7a333eSShuo Chen}
944b7a333eSShuo Chen
95