Poller.cc revision 40161064
140161064SShuo Chen// excerpts from http://code.google.com/p/muduo/
240161064SShuo Chen//
340161064SShuo Chen// Use of this source code is governed by a BSD-style license
440161064SShuo Chen// that can be found in the License file.
540161064SShuo Chen//
640161064SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
740161064SShuo Chen
840161064SShuo Chen#include "Poller.h"
940161064SShuo Chen
1040161064SShuo Chen#include "Channel.h"
1140161064SShuo Chen#include "logging/Logging.h"
1240161064SShuo Chen
1340161064SShuo Chen#include <assert.h>
1440161064SShuo Chen#include <poll.h>
1540161064SShuo Chen
1640161064SShuo Chenusing namespace muduo;
1740161064SShuo Chen
1840161064SShuo ChenPoller::Poller(EventLoop* loop)
1940161064SShuo Chen  : ownerLoop_(loop)
2040161064SShuo Chen{
2140161064SShuo Chen}
2240161064SShuo Chen
2340161064SShuo ChenPoller::~Poller()
2440161064SShuo Chen{
2540161064SShuo Chen}
2640161064SShuo Chen
2740161064SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
2840161064SShuo Chen{
2940161064SShuo Chen  // XXX pollfds_ shouldn't change
3040161064SShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
3140161064SShuo Chen  Timestamp now(Timestamp::now());
3240161064SShuo Chen  if (numEvents > 0) {
3340161064SShuo Chen    LOG_TRACE << numEvents << " events happended";
3440161064SShuo Chen    fillActiveChannels(numEvents, activeChannels);
3540161064SShuo Chen  } else if (numEvents == 0) {
3640161064SShuo Chen    LOG_TRACE << " nothing happended";
3740161064SShuo Chen  } else {
3840161064SShuo Chen    LOG_SYSERR << "Poller::poll()";
3940161064SShuo Chen  }
4040161064SShuo Chen  return now;
4140161064SShuo Chen}
4240161064SShuo Chen
4340161064SShuo Chenvoid Poller::fillActiveChannels(int numEvents,
4440161064SShuo Chen                                ChannelList* activeChannels) const
4540161064SShuo Chen{
4640161064SShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
4740161064SShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
4840161064SShuo Chen  {
4940161064SShuo Chen    if (pfd->revents > 0)
5040161064SShuo Chen    {
5140161064SShuo Chen      --numEvents;
5240161064SShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
5340161064SShuo Chen      assert(ch != channels_.end());
5440161064SShuo Chen      Channel* channel = ch->second;
5540161064SShuo Chen      assert(channel->fd() == pfd->fd);
5640161064SShuo Chen      channel->set_revents(pfd->revents);
5740161064SShuo Chen      // pfd->revents = 0;
5840161064SShuo Chen      activeChannels->push_back(channel);
5940161064SShuo Chen    }
6040161064SShuo Chen  }
6140161064SShuo Chen}
6240161064SShuo Chen
6340161064SShuo Chenvoid Poller::updateChannel(Channel* channel)
6440161064SShuo Chen{
6540161064SShuo Chen  assertInLoopThread();
6640161064SShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
6740161064SShuo Chen  if (channel->index() < 0) {
6840161064SShuo Chen    // a new one, add to pollfds_
6940161064SShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
7040161064SShuo Chen    struct pollfd pfd;
7140161064SShuo Chen    pfd.fd = channel->fd();
7240161064SShuo Chen    pfd.events = static_cast<short>(channel->events());
7340161064SShuo Chen    pfd.revents = 0;
7440161064SShuo Chen    pollfds_.push_back(pfd);
7540161064SShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
7640161064SShuo Chen    channel->set_index(idx);
7740161064SShuo Chen    channels_[pfd.fd] = channel;
7840161064SShuo Chen  } else {
7940161064SShuo Chen    // update existing one
8040161064SShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
8140161064SShuo Chen    assert(channels_[channel->fd()] == channel);
8240161064SShuo Chen    int idx = channel->index();
8340161064SShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
8440161064SShuo Chen    struct pollfd& pfd = pollfds_[idx];
8540161064SShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
8640161064SShuo Chen    pfd.events = static_cast<short>(channel->events());
8740161064SShuo Chen    pfd.revents = 0;
8840161064SShuo Chen    if (channel->isNoneEvent()) {
8940161064SShuo Chen      // ignore this pollfd
9040161064SShuo Chen      pfd.fd = -channel->fd()-1;
9140161064SShuo Chen    }
9240161064SShuo Chen  }
9340161064SShuo Chen}
9440161064SShuo Chen
9540161064SShuo Chenvoid Poller::removeChannel(Channel* channel)
9640161064SShuo Chen{
9740161064SShuo Chen  assertInLoopThread();
9840161064SShuo Chen  LOG_TRACE << "fd = " << channel->fd();
9940161064SShuo Chen  assert(channels_.find(channel->fd()) != channels_.end());
10040161064SShuo Chen  assert(channels_[channel->fd()] == channel);
10140161064SShuo Chen  assert(channel->isNoneEvent());
10240161064SShuo Chen  int idx = channel->index();
10340161064SShuo Chen  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
10440161064SShuo Chen  const struct pollfd& pfd = pollfds_[idx]; (void)pfd;
10540161064SShuo Chen  assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
10640161064SShuo Chen  size_t n = channels_.erase(channel->fd());
10740161064SShuo Chen  assert(n == 1); (void)n;
10840161064SShuo Chen  if (implicit_cast<size_t>(idx) == pollfds_.size()-1) {
10940161064SShuo Chen    pollfds_.pop_back();
11040161064SShuo Chen  } else {
11140161064SShuo Chen    int channelAtEnd = pollfds_.back().fd;
11240161064SShuo Chen    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
11340161064SShuo Chen    if (channelAtEnd < 0) {
11440161064SShuo Chen      channelAtEnd = -channelAtEnd-1;
11540161064SShuo Chen    }
11640161064SShuo Chen    channels_[channelAtEnd]->set_index(idx);
11740161064SShuo Chen    pollfds_.pop_back();
11840161064SShuo Chen  }
11940161064SShuo Chen}
12040161064SShuo Chen
121