Poller.cc revision 17c057c3
1bfe73648SShuo Chen// excerpts from http://code.google.com/p/muduo/
2bfe73648SShuo Chen//
3bfe73648SShuo Chen// Use of this source code is governed by a BSD-style license
4bfe73648SShuo Chen// that can be found in the License file.
5bfe73648SShuo Chen//
6bfe73648SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7bfe73648SShuo Chen
8bfe73648SShuo Chen#include "Poller.h"
9bfe73648SShuo Chen
10bfe73648SShuo Chen#include "Channel.h"
11bfe73648SShuo Chen#include "logging/Logging.h"
12bfe73648SShuo Chen
13bfe73648SShuo Chen#include <assert.h>
14bfe73648SShuo Chen#include <poll.h>
15bfe73648SShuo Chen
16bfe73648SShuo Chenusing namespace muduo;
17bfe73648SShuo Chen
18bfe73648SShuo ChenPoller::Poller(EventLoop* loop)
19bfe73648SShuo Chen  : ownerLoop_(loop)
20bfe73648SShuo Chen{
21bfe73648SShuo Chen}
22bfe73648SShuo Chen
23bfe73648SShuo ChenPoller::~Poller()
24bfe73648SShuo Chen{
25bfe73648SShuo Chen}
26bfe73648SShuo Chen
27bfe73648SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
28bfe73648SShuo Chen{
29bfe73648SShuo Chen  // XXX pollfds_ shouldn't change
30bfe73648SShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
31bfe73648SShuo Chen  Timestamp now(Timestamp::now());
32bfe73648SShuo Chen  if (numEvents > 0)
33bfe73648SShuo Chen  {
34bfe73648SShuo Chen    LOG_TRACE << numEvents << " events happended";
35bfe73648SShuo Chen    fillActiveChannels(numEvents, activeChannels);
36bfe73648SShuo Chen  }
37bfe73648SShuo Chen  else if (numEvents == 0)
38bfe73648SShuo Chen  {
39bfe73648SShuo Chen    LOG_TRACE << " nothing happended";
40bfe73648SShuo Chen  }
41bfe73648SShuo Chen  else
42bfe73648SShuo Chen  {
43bfe73648SShuo Chen    LOG_SYSERR << "Poller::poll()";
44bfe73648SShuo Chen  }
45bfe73648SShuo Chen  return now;
46bfe73648SShuo Chen}
47bfe73648SShuo Chen
48bfe73648SShuo Chenvoid Poller::fillActiveChannels(int numEvents,
49bfe73648SShuo Chen                                ChannelList* activeChannels) const
50bfe73648SShuo Chen{
51bfe73648SShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
52bfe73648SShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
53bfe73648SShuo Chen  {
54bfe73648SShuo Chen    if (pfd->revents > 0)
55bfe73648SShuo Chen    {
56bfe73648SShuo Chen      --numEvents;
57bfe73648SShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
58bfe73648SShuo Chen      assert(ch != channels_.end());
59bfe73648SShuo Chen      Channel* channel = ch->second;
60bfe73648SShuo Chen      assert(channel->fd() == pfd->fd);
61bfe73648SShuo Chen      channel->set_revents(pfd->revents);
62bfe73648SShuo Chen      // pfd->revents = 0;
63bfe73648SShuo Chen      activeChannels->push_back(channel);
64bfe73648SShuo Chen    }
65bfe73648SShuo Chen  }
66bfe73648SShuo Chen}
67bfe73648SShuo Chen
68bfe73648SShuo Chenvoid Poller::updateChannel(Channel* channel)
69bfe73648SShuo Chen{
7017c057c3SShuo Chen  assertInLoopThread();
71bfe73648SShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
72bfe73648SShuo Chen  if (channel->index() < 0)
73bfe73648SShuo Chen  {
74bfe73648SShuo Chen    // a new one, add to pollfds_
75bfe73648SShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
76bfe73648SShuo Chen    struct pollfd pfd;
77bfe73648SShuo Chen    pfd.fd = channel->fd();
78bfe73648SShuo Chen    pfd.events = static_cast<short>(channel->events());
79bfe73648SShuo Chen    pfd.revents = 0;
80bfe73648SShuo Chen    pollfds_.push_back(pfd);
81bfe73648SShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
82bfe73648SShuo Chen    channel->set_index(idx);
83bfe73648SShuo Chen    channels_[pfd.fd] = channel;
84bfe73648SShuo Chen  }
85bfe73648SShuo Chen  else
86bfe73648SShuo Chen  {
87bfe73648SShuo Chen    // update existing one
88bfe73648SShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
89bfe73648SShuo Chen    assert(channels_[channel->fd()] == channel);
90bfe73648SShuo Chen    int idx = channel->index();
91bfe73648SShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
92bfe73648SShuo Chen    struct pollfd& pfd = pollfds_[idx];
9317c057c3SShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
9417c057c3SShuo Chen    pfd.events = static_cast<short>(channel->events());
9517c057c3SShuo Chen    pfd.revents = 0;
960615e80eSShuo Chen    if (channel->isNoneEvent())
97bfe73648SShuo Chen    {
98bfe73648SShuo Chen      // ignore this pollfd
9917c057c3SShuo Chen      pfd.fd = -channel->fd()-1;
10017c057c3SShuo Chen    }
10117c057c3SShuo Chen  }
10217c057c3SShuo Chen}
10317c057c3SShuo Chen
10417c057c3SShuo Chenvoid Poller::removeChannel(Channel* channel)
10517c057c3SShuo Chen{
10617c057c3SShuo Chen  assertInLoopThread();
10717c057c3SShuo Chen  LOG_TRACE << "fd = " << channel->fd();
10817c057c3SShuo Chen  assert(channels_.find(channel->fd()) != channels_.end());
10917c057c3SShuo Chen  assert(channels_[channel->fd()] == channel);
11017c057c3SShuo Chen  assert(channel->isNoneEvent());
11117c057c3SShuo Chen  int idx = channel->index();
11217c057c3SShuo Chen  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
11317c057c3SShuo Chen  const struct pollfd& pfd = pollfds_[idx]; (void)pfd;
11417c057c3SShuo Chen  assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
11517c057c3SShuo Chen  size_t n = channels_.erase(channel->fd());
11617c057c3SShuo Chen  assert(n == 1); (void)n;
11717c057c3SShuo Chen  if (implicit_cast<size_t>(idx) == pollfds_.size()-1)
11817c057c3SShuo Chen  {
11917c057c3SShuo Chen    pollfds_.pop_back();
12017c057c3SShuo Chen  }
12117c057c3SShuo Chen  else
12217c057c3SShuo Chen  {
12317c057c3SShuo Chen    int channelAtEnd = pollfds_.back().fd;
12417c057c3SShuo Chen    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
12517c057c3SShuo Chen    if (channelAtEnd < 0)
12617c057c3SShuo Chen    {
12717c057c3SShuo Chen      channelAtEnd = -channelAtEnd-1;
128bfe73648SShuo Chen    }
12917c057c3SShuo Chen    channels_[channelAtEnd]->set_index(idx);
13017c057c3SShuo Chen    pollfds_.pop_back();
131bfe73648SShuo Chen  }
132bfe73648SShuo Chen}
133bfe73648SShuo Chen
134