19a1e991dSShuo Chen// excerpts from http://code.google.com/p/muduo/
29a1e991dSShuo Chen//
39a1e991dSShuo Chen// Use of this source code is governed by a BSD-style license
49a1e991dSShuo Chen// that can be found in the License file.
59a1e991dSShuo Chen//
69a1e991dSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
79a1e991dSShuo Chen
89a1e991dSShuo Chen#include "Poller.h"
99a1e991dSShuo Chen
109a1e991dSShuo Chen#include "Channel.h"
119a1e991dSShuo Chen#include "logging/Logging.h"
129a1e991dSShuo Chen
139a1e991dSShuo Chen#include <assert.h>
149a1e991dSShuo Chen#include <poll.h>
159a1e991dSShuo Chen
169a1e991dSShuo Chenusing namespace muduo;
179a1e991dSShuo Chen
189a1e991dSShuo ChenPoller::Poller(EventLoop* loop)
199a1e991dSShuo Chen  : ownerLoop_(loop)
209a1e991dSShuo Chen{
219a1e991dSShuo Chen}
229a1e991dSShuo Chen
239a1e991dSShuo ChenPoller::~Poller()
249a1e991dSShuo Chen{
259a1e991dSShuo Chen}
269a1e991dSShuo Chen
279a1e991dSShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
289a1e991dSShuo Chen{
299a1e991dSShuo Chen  // XXX pollfds_ shouldn't change
309a1e991dSShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
319a1e991dSShuo Chen  Timestamp now(Timestamp::now());
32b4a5ce52SShuo Chen  if (numEvents > 0) {
339a1e991dSShuo Chen    LOG_TRACE << numEvents << " events happended";
349a1e991dSShuo Chen    fillActiveChannels(numEvents, activeChannels);
35b4a5ce52SShuo Chen  } else if (numEvents == 0) {
369a1e991dSShuo Chen    LOG_TRACE << " nothing happended";
37b4a5ce52SShuo Chen  } else {
389a1e991dSShuo Chen    LOG_SYSERR << "Poller::poll()";
399a1e991dSShuo Chen  }
409a1e991dSShuo Chen  return now;
419a1e991dSShuo Chen}
429a1e991dSShuo Chen
439a1e991dSShuo Chenvoid Poller::fillActiveChannels(int numEvents,
449a1e991dSShuo Chen                                ChannelList* activeChannels) const
459a1e991dSShuo Chen{
469a1e991dSShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
479a1e991dSShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
489a1e991dSShuo Chen  {
499a1e991dSShuo Chen    if (pfd->revents > 0)
509a1e991dSShuo Chen    {
519a1e991dSShuo Chen      --numEvents;
529a1e991dSShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
539a1e991dSShuo Chen      assert(ch != channels_.end());
549a1e991dSShuo Chen      Channel* channel = ch->second;
559a1e991dSShuo Chen      assert(channel->fd() == pfd->fd);
569a1e991dSShuo Chen      channel->set_revents(pfd->revents);
579a1e991dSShuo Chen      // pfd->revents = 0;
589a1e991dSShuo Chen      activeChannels->push_back(channel);
599a1e991dSShuo Chen    }
609a1e991dSShuo Chen  }
619a1e991dSShuo Chen}
629a1e991dSShuo Chen
639a1e991dSShuo Chenvoid Poller::updateChannel(Channel* channel)
649a1e991dSShuo Chen{
65ee021d99SShuo Chen  assertInLoopThread();
669a1e991dSShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
67b4a5ce52SShuo Chen  if (channel->index() < 0) {
689a1e991dSShuo Chen    // a new one, add to pollfds_
699a1e991dSShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
709a1e991dSShuo Chen    struct pollfd pfd;
719a1e991dSShuo Chen    pfd.fd = channel->fd();
729a1e991dSShuo Chen    pfd.events = static_cast<short>(channel->events());
739a1e991dSShuo Chen    pfd.revents = 0;
749a1e991dSShuo Chen    pollfds_.push_back(pfd);
759a1e991dSShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
769a1e991dSShuo Chen    channel->set_index(idx);
779a1e991dSShuo Chen    channels_[pfd.fd] = channel;
78b4a5ce52SShuo Chen  } else {
799a1e991dSShuo Chen    // update existing one
809a1e991dSShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
819a1e991dSShuo Chen    assert(channels_[channel->fd()] == channel);
829a1e991dSShuo Chen    int idx = channel->index();
839a1e991dSShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
849a1e991dSShuo Chen    struct pollfd& pfd = pollfds_[idx];
859a1e991dSShuo 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()) {
899a1e991dSShuo Chen      // ignore this pollfd
909a1e991dSShuo Chen      pfd.fd = -1;
919a1e991dSShuo Chen    }
929a1e991dSShuo Chen  }
939a1e991dSShuo Chen}
949a1e991dSShuo Chen
95