Poller.cc revision 65c497a3
165c497a3SShuo Chen// excerpts from http://code.google.com/p/muduo/
265c497a3SShuo Chen//
365c497a3SShuo Chen// Use of this source code is governed by a BSD-style license
465c497a3SShuo Chen// that can be found in the License file.
565c497a3SShuo Chen//
665c497a3SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
765c497a3SShuo Chen
865c497a3SShuo Chen#include "Poller.h"
965c497a3SShuo Chen
1065c497a3SShuo Chen#include "Channel.h"
1165c497a3SShuo Chen#include "logging/Logging.h"
1265c497a3SShuo Chen
1365c497a3SShuo Chen#include <assert.h>
1465c497a3SShuo Chen#include <poll.h>
1565c497a3SShuo Chen
1665c497a3SShuo Chenusing namespace muduo;
1765c497a3SShuo Chen
1865c497a3SShuo ChenPoller::Poller(EventLoop* loop)
1965c497a3SShuo Chen  : ownerLoop_(loop)
2065c497a3SShuo Chen{
2165c497a3SShuo Chen}
2265c497a3SShuo Chen
2365c497a3SShuo ChenPoller::~Poller()
2465c497a3SShuo Chen{
2565c497a3SShuo Chen}
2665c497a3SShuo Chen
2765c497a3SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
2865c497a3SShuo Chen{
2965c497a3SShuo Chen  // XXX pollfds_ shouldn't change
3065c497a3SShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
3165c497a3SShuo Chen  Timestamp now(Timestamp::now());
3265c497a3SShuo Chen  if (numEvents > 0)
3365c497a3SShuo Chen  {
3465c497a3SShuo Chen    LOG_TRACE << numEvents << " events happended";
3565c497a3SShuo Chen    fillActiveChannels(numEvents, activeChannels);
3665c497a3SShuo Chen  }
3765c497a3SShuo Chen  else if (numEvents == 0)
3865c497a3SShuo Chen  {
3965c497a3SShuo Chen    LOG_TRACE << " nothing happended";
4065c497a3SShuo Chen  }
4165c497a3SShuo Chen  else
4265c497a3SShuo Chen  {
4365c497a3SShuo Chen    LOG_SYSERR << "Poller::poll()";
4465c497a3SShuo Chen  }
4565c497a3SShuo Chen  return now;
4665c497a3SShuo Chen}
4765c497a3SShuo Chen
4865c497a3SShuo Chenvoid Poller::fillActiveChannels(int numEvents,
4965c497a3SShuo Chen                                ChannelList* activeChannels) const
5065c497a3SShuo Chen{
5165c497a3SShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
5265c497a3SShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
5365c497a3SShuo Chen  {
5465c497a3SShuo Chen    if (pfd->revents > 0)
5565c497a3SShuo Chen    {
5665c497a3SShuo Chen      --numEvents;
5765c497a3SShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
5865c497a3SShuo Chen      assert(ch != channels_.end());
5965c497a3SShuo Chen      Channel* channel = ch->second;
6065c497a3SShuo Chen      assert(channel->fd() == pfd->fd);
6165c497a3SShuo Chen      channel->set_revents(pfd->revents);
6265c497a3SShuo Chen      // pfd->revents = 0;
6365c497a3SShuo Chen      activeChannels->push_back(channel);
6465c497a3SShuo Chen    }
6565c497a3SShuo Chen  }
6665c497a3SShuo Chen}
6765c497a3SShuo Chen
6865c497a3SShuo Chenvoid Poller::updateChannel(Channel* channel)
6965c497a3SShuo Chen{
7065c497a3SShuo Chen  assertInLoopThread();
7165c497a3SShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
7265c497a3SShuo Chen  if (channel->index() < 0)
7365c497a3SShuo Chen  {
7465c497a3SShuo Chen    // a new one, add to pollfds_
7565c497a3SShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
7665c497a3SShuo Chen    struct pollfd pfd;
7765c497a3SShuo Chen    pfd.fd = channel->fd();
7865c497a3SShuo Chen    pfd.events = static_cast<short>(channel->events());
7965c497a3SShuo Chen    pfd.revents = 0;
8065c497a3SShuo Chen    pollfds_.push_back(pfd);
8165c497a3SShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
8265c497a3SShuo Chen    channel->set_index(idx);
8365c497a3SShuo Chen    channels_[pfd.fd] = channel;
8465c497a3SShuo Chen  }
8565c497a3SShuo Chen  else
8665c497a3SShuo Chen  {
8765c497a3SShuo Chen    // update existing one
8865c497a3SShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
8965c497a3SShuo Chen    assert(channels_[channel->fd()] == channel);
9065c497a3SShuo Chen    int idx = channel->index();
9165c497a3SShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
9265c497a3SShuo Chen    struct pollfd& pfd = pollfds_[idx];
9365c497a3SShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
9465c497a3SShuo Chen    pfd.events = static_cast<short>(channel->events());
9565c497a3SShuo Chen    pfd.revents = 0;
9665c497a3SShuo Chen    if (channel->isNoneEvent())
9765c497a3SShuo Chen    {
9865c497a3SShuo Chen      // ignore this pollfd
9965c497a3SShuo Chen      pfd.fd = -channel->fd()-1;
10065c497a3SShuo Chen    }
10165c497a3SShuo Chen  }
10265c497a3SShuo Chen}
10365c497a3SShuo Chen
10465c497a3SShuo Chenvoid Poller::removeChannel(Channel* channel)
10565c497a3SShuo Chen{
10665c497a3SShuo Chen  assertInLoopThread();
10765c497a3SShuo Chen  LOG_TRACE << "fd = " << channel->fd();
10865c497a3SShuo Chen  assert(channels_.find(channel->fd()) != channels_.end());
10965c497a3SShuo Chen  assert(channels_[channel->fd()] == channel);
11065c497a3SShuo Chen  assert(channel->isNoneEvent());
11165c497a3SShuo Chen  int idx = channel->index();
11265c497a3SShuo Chen  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
11365c497a3SShuo Chen  const struct pollfd& pfd = pollfds_[idx]; (void)pfd;
11465c497a3SShuo Chen  assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
11565c497a3SShuo Chen  size_t n = channels_.erase(channel->fd());
11665c497a3SShuo Chen  assert(n == 1); (void)n;
11765c497a3SShuo Chen  if (implicit_cast<size_t>(idx) == pollfds_.size()-1)
11865c497a3SShuo Chen  {
11965c497a3SShuo Chen    pollfds_.pop_back();
12065c497a3SShuo Chen  }
12165c497a3SShuo Chen  else
12265c497a3SShuo Chen  {
12365c497a3SShuo Chen    int channelAtEnd = pollfds_.back().fd;
12465c497a3SShuo Chen    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
12565c497a3SShuo Chen    if (channelAtEnd < 0)
12665c497a3SShuo Chen    {
12765c497a3SShuo Chen      channelAtEnd = -channelAtEnd-1;
12865c497a3SShuo Chen    }
12965c497a3SShuo Chen    channels_[channelAtEnd]->set_index(idx);
13065c497a3SShuo Chen    pollfds_.pop_back();
13165c497a3SShuo Chen  }
13265c497a3SShuo Chen}
13365c497a3SShuo Chen
134