Poller.cc revision b37003a7
1b37003a7SShuo Chen// excerpts from http://code.google.com/p/muduo/
2b37003a7SShuo Chen//
3b37003a7SShuo Chen// Use of this source code is governed by a BSD-style license
4b37003a7SShuo Chen// that can be found in the License file.
5b37003a7SShuo Chen//
6b37003a7SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7b37003a7SShuo Chen
8b37003a7SShuo Chen#include "Poller.h"
9b37003a7SShuo Chen
10b37003a7SShuo Chen#include "Channel.h"
11b37003a7SShuo Chen#include "logging/Logging.h"
12b37003a7SShuo Chen
13b37003a7SShuo Chen#include <assert.h>
14b37003a7SShuo Chen#include <poll.h>
15b37003a7SShuo Chen
16b37003a7SShuo Chenusing namespace muduo;
17b37003a7SShuo Chen
18b37003a7SShuo ChenPoller::Poller(EventLoop* loop)
19b37003a7SShuo Chen  : ownerLoop_(loop)
20b37003a7SShuo Chen{
21b37003a7SShuo Chen}
22b37003a7SShuo Chen
23b37003a7SShuo ChenPoller::~Poller()
24b37003a7SShuo Chen{
25b37003a7SShuo Chen}
26b37003a7SShuo Chen
27b37003a7SShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
28b37003a7SShuo Chen{
29b37003a7SShuo Chen  // XXX pollfds_ shouldn't change
30b37003a7SShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
31b37003a7SShuo Chen  Timestamp now(Timestamp::now());
32b37003a7SShuo Chen  if (numEvents > 0)
33b37003a7SShuo Chen  {
34b37003a7SShuo Chen    LOG_TRACE << numEvents << " events happended";
35b37003a7SShuo Chen    fillActiveChannels(numEvents, activeChannels);
36b37003a7SShuo Chen  }
37b37003a7SShuo Chen  else if (numEvents == 0)
38b37003a7SShuo Chen  {
39b37003a7SShuo Chen    LOG_TRACE << " nothing happended";
40b37003a7SShuo Chen  }
41b37003a7SShuo Chen  else
42b37003a7SShuo Chen  {
43b37003a7SShuo Chen    LOG_SYSERR << "Poller::poll()";
44b37003a7SShuo Chen  }
45b37003a7SShuo Chen  return now;
46b37003a7SShuo Chen}
47b37003a7SShuo Chen
48b37003a7SShuo Chenvoid Poller::fillActiveChannels(int numEvents,
49b37003a7SShuo Chen                                ChannelList* activeChannels) const
50b37003a7SShuo Chen{
51b37003a7SShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
52b37003a7SShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
53b37003a7SShuo Chen  {
54b37003a7SShuo Chen    if (pfd->revents > 0)
55b37003a7SShuo Chen    {
56b37003a7SShuo Chen      --numEvents;
57b37003a7SShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
58b37003a7SShuo Chen      assert(ch != channels_.end());
59b37003a7SShuo Chen      Channel* channel = ch->second;
60b37003a7SShuo Chen      assert(channel->fd() == pfd->fd);
61b37003a7SShuo Chen      channel->set_revents(pfd->revents);
62b37003a7SShuo Chen      // pfd->revents = 0;
63b37003a7SShuo Chen      activeChannels->push_back(channel);
64b37003a7SShuo Chen    }
65b37003a7SShuo Chen  }
66b37003a7SShuo Chen}
67b37003a7SShuo Chen
68b37003a7SShuo Chenvoid Poller::updateChannel(Channel* channel)
69b37003a7SShuo Chen{
70b37003a7SShuo Chen  assertInLoopThread();
71b37003a7SShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
72b37003a7SShuo Chen  if (channel->index() < 0)
73b37003a7SShuo Chen  {
74b37003a7SShuo Chen    // a new one, add to pollfds_
75b37003a7SShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
76b37003a7SShuo Chen    struct pollfd pfd;
77b37003a7SShuo Chen    pfd.fd = channel->fd();
78b37003a7SShuo Chen    pfd.events = static_cast<short>(channel->events());
79b37003a7SShuo Chen    pfd.revents = 0;
80b37003a7SShuo Chen    pollfds_.push_back(pfd);
81b37003a7SShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
82b37003a7SShuo Chen    channel->set_index(idx);
83b37003a7SShuo Chen    channels_[pfd.fd] = channel;
84b37003a7SShuo Chen  }
85b37003a7SShuo Chen  else
86b37003a7SShuo Chen  {
87b37003a7SShuo Chen    // update existing one
88b37003a7SShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
89b37003a7SShuo Chen    assert(channels_[channel->fd()] == channel);
90b37003a7SShuo Chen    int idx = channel->index();
91b37003a7SShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
92b37003a7SShuo Chen    struct pollfd& pfd = pollfds_[idx];
93b37003a7SShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
94b37003a7SShuo Chen    pfd.events = static_cast<short>(channel->events());
95b37003a7SShuo Chen    pfd.revents = 0;
96b37003a7SShuo Chen    if (channel->isNoneEvent())
97b37003a7SShuo Chen    {
98b37003a7SShuo Chen      // ignore this pollfd
99b37003a7SShuo Chen      pfd.fd = -channel->fd()-1;
100b37003a7SShuo Chen    }
101b37003a7SShuo Chen  }
102b37003a7SShuo Chen}
103b37003a7SShuo Chen
104b37003a7SShuo Chenvoid Poller::removeChannel(Channel* channel)
105b37003a7SShuo Chen{
106b37003a7SShuo Chen  assertInLoopThread();
107b37003a7SShuo Chen  LOG_TRACE << "fd = " << channel->fd();
108b37003a7SShuo Chen  assert(channels_.find(channel->fd()) != channels_.end());
109b37003a7SShuo Chen  assert(channels_[channel->fd()] == channel);
110b37003a7SShuo Chen  assert(channel->isNoneEvent());
111b37003a7SShuo Chen  int idx = channel->index();
112b37003a7SShuo Chen  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
113b37003a7SShuo Chen  const struct pollfd& pfd = pollfds_[idx]; (void)pfd;
114b37003a7SShuo Chen  assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
115b37003a7SShuo Chen  size_t n = channels_.erase(channel->fd());
116b37003a7SShuo Chen  assert(n == 1); (void)n;
117b37003a7SShuo Chen  if (implicit_cast<size_t>(idx) == pollfds_.size()-1)
118b37003a7SShuo Chen  {
119b37003a7SShuo Chen    pollfds_.pop_back();
120b37003a7SShuo Chen  }
121b37003a7SShuo Chen  else
122b37003a7SShuo Chen  {
123b37003a7SShuo Chen    int channelAtEnd = pollfds_.back().fd;
124b37003a7SShuo Chen    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
125b37003a7SShuo Chen    if (channelAtEnd < 0)
126b37003a7SShuo Chen    {
127b37003a7SShuo Chen      channelAtEnd = -channelAtEnd-1;
128b37003a7SShuo Chen    }
129b37003a7SShuo Chen    channels_[channelAtEnd]->set_index(idx);
130b37003a7SShuo Chen    pollfds_.pop_back();
131b37003a7SShuo Chen  }
132b37003a7SShuo Chen}
133b37003a7SShuo Chen
134