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