1cbe8e7d0SShuo Chen// excerpts from http://code.google.com/p/muduo/
2cbe8e7d0SShuo Chen//
3cbe8e7d0SShuo Chen// Use of this source code is governed by a BSD-style license
4cbe8e7d0SShuo Chen// that can be found in the License file.
5cbe8e7d0SShuo Chen//
6cbe8e7d0SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7cbe8e7d0SShuo Chen
8cbe8e7d0SShuo Chen#include "Poller.h"
9cbe8e7d0SShuo Chen
10cbe8e7d0SShuo Chen#include "Channel.h"
11cbe8e7d0SShuo Chen#include "logging/Logging.h"
12cbe8e7d0SShuo Chen
13cbe8e7d0SShuo Chen#include <assert.h>
14cbe8e7d0SShuo Chen#include <poll.h>
15cbe8e7d0SShuo Chen
16cbe8e7d0SShuo Chenusing namespace muduo;
17cbe8e7d0SShuo Chen
18cbe8e7d0SShuo ChenPoller::Poller(EventLoop* loop)
19cbe8e7d0SShuo Chen  : ownerLoop_(loop)
20cbe8e7d0SShuo Chen{
21cbe8e7d0SShuo Chen}
22cbe8e7d0SShuo Chen
23cbe8e7d0SShuo ChenPoller::~Poller()
24cbe8e7d0SShuo Chen{
25cbe8e7d0SShuo Chen}
26cbe8e7d0SShuo Chen
27cbe8e7d0SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
28cbe8e7d0SShuo Chen{
29cbe8e7d0SShuo Chen  // XXX pollfds_ shouldn't change
30cbe8e7d0SShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
31cbe8e7d0SShuo Chen  Timestamp now(Timestamp::now());
32b4a5ce52SShuo Chen  if (numEvents > 0) {
33cbe8e7d0SShuo Chen    LOG_TRACE << numEvents << " events happended";
34cbe8e7d0SShuo Chen    fillActiveChannels(numEvents, activeChannels);
35b4a5ce52SShuo Chen  } else if (numEvents == 0) {
36cbe8e7d0SShuo Chen    LOG_TRACE << " nothing happended";
37b4a5ce52SShuo Chen  } else {
38cbe8e7d0SShuo Chen    LOG_SYSERR << "Poller::poll()";
39cbe8e7d0SShuo Chen  }
40cbe8e7d0SShuo Chen  return now;
41cbe8e7d0SShuo Chen}
42cbe8e7d0SShuo Chen
43cbe8e7d0SShuo Chenvoid Poller::fillActiveChannels(int numEvents,
44cbe8e7d0SShuo Chen                                ChannelList* activeChannels) const
45cbe8e7d0SShuo Chen{
46cbe8e7d0SShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
47cbe8e7d0SShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
48cbe8e7d0SShuo Chen  {
49cbe8e7d0SShuo Chen    if (pfd->revents > 0)
50cbe8e7d0SShuo Chen    {
51cbe8e7d0SShuo Chen      --numEvents;
52cbe8e7d0SShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
53cbe8e7d0SShuo Chen      assert(ch != channels_.end());
54cbe8e7d0SShuo Chen      Channel* channel = ch->second;
55cbe8e7d0SShuo Chen      assert(channel->fd() == pfd->fd);
56cbe8e7d0SShuo Chen      channel->set_revents(pfd->revents);
57cbe8e7d0SShuo Chen      // pfd->revents = 0;
58cbe8e7d0SShuo Chen      activeChannels->push_back(channel);
59cbe8e7d0SShuo Chen    }
60cbe8e7d0SShuo Chen  }
61cbe8e7d0SShuo Chen}
62cbe8e7d0SShuo Chen
63cbe8e7d0SShuo Chenvoid Poller::updateChannel(Channel* channel)
64cbe8e7d0SShuo Chen{
65ee021d99SShuo Chen  assertInLoopThread();
66cbe8e7d0SShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
67b4a5ce52SShuo Chen  if (channel->index() < 0) {
68cbe8e7d0SShuo Chen    // a new one, add to pollfds_
69cbe8e7d0SShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
70cbe8e7d0SShuo Chen    struct pollfd pfd;
71cbe8e7d0SShuo Chen    pfd.fd = channel->fd();
72cbe8e7d0SShuo Chen    pfd.events = static_cast<short>(channel->events());
73cbe8e7d0SShuo Chen    pfd.revents = 0;
74cbe8e7d0SShuo Chen    pollfds_.push_back(pfd);
75cbe8e7d0SShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
76cbe8e7d0SShuo Chen    channel->set_index(idx);
77cbe8e7d0SShuo Chen    channels_[pfd.fd] = channel;
78b4a5ce52SShuo Chen  } else {
79cbe8e7d0SShuo Chen    // update existing one
80cbe8e7d0SShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
81cbe8e7d0SShuo Chen    assert(channels_[channel->fd()] == channel);
82cbe8e7d0SShuo Chen    int idx = channel->index();
83cbe8e7d0SShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
84cbe8e7d0SShuo Chen    struct pollfd& pfd = pollfds_[idx];
85cbe8e7d0SShuo 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()) {
89cbe8e7d0SShuo Chen      // ignore this pollfd
90cbe8e7d0SShuo Chen      pfd.fd = -1;
91cbe8e7d0SShuo Chen    }
92cbe8e7d0SShuo Chen  }
93cbe8e7d0SShuo Chen}
94cbe8e7d0SShuo Chen
95