Poller.cc revision 4b7a333e
14b7a333eSShuo Chen// excerpts from http://code.google.com/p/muduo/
24b7a333eSShuo Chen//
34b7a333eSShuo Chen// Use of this source code is governed by a BSD-style license
44b7a333eSShuo Chen// that can be found in the License file.
54b7a333eSShuo Chen//
64b7a333eSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
74b7a333eSShuo Chen
84b7a333eSShuo Chen#include "Poller.h"
94b7a333eSShuo Chen
104b7a333eSShuo Chen#include "Channel.h"
114b7a333eSShuo Chen#include "logging/Logging.h"
124b7a333eSShuo Chen
134b7a333eSShuo Chen#include <assert.h>
144b7a333eSShuo Chen#include <poll.h>
154b7a333eSShuo Chen
164b7a333eSShuo Chenusing namespace muduo;
174b7a333eSShuo Chen
184b7a333eSShuo ChenPoller::Poller(EventLoop* loop)
194b7a333eSShuo Chen  : ownerLoop_(loop)
204b7a333eSShuo Chen{
214b7a333eSShuo Chen}
224b7a333eSShuo Chen
234b7a333eSShuo ChenPoller::~Poller()
244b7a333eSShuo Chen{
254b7a333eSShuo Chen}
264b7a333eSShuo Chen
274b7a333eSShuo ChenTimestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
284b7a333eSShuo Chen{
294b7a333eSShuo Chen  // XXX pollfds_ shouldn't change
304b7a333eSShuo Chen  int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
314b7a333eSShuo Chen  Timestamp now(Timestamp::now());
324b7a333eSShuo Chen  if (numEvents > 0)
334b7a333eSShuo Chen  {
344b7a333eSShuo Chen    LOG_TRACE << numEvents << " events happended";
354b7a333eSShuo Chen    fillActiveChannels(numEvents, activeChannels);
364b7a333eSShuo Chen  }
374b7a333eSShuo Chen  else if (numEvents == 0)
384b7a333eSShuo Chen  {
394b7a333eSShuo Chen    LOG_TRACE << " nothing happended";
404b7a333eSShuo Chen  }
414b7a333eSShuo Chen  else
424b7a333eSShuo Chen  {
434b7a333eSShuo Chen    LOG_SYSERR << "Poller::poll()";
444b7a333eSShuo Chen  }
454b7a333eSShuo Chen  return now;
464b7a333eSShuo Chen}
474b7a333eSShuo Chen
484b7a333eSShuo Chenvoid Poller::fillActiveChannels(int numEvents,
494b7a333eSShuo Chen                                ChannelList* activeChannels) const
504b7a333eSShuo Chen{
514b7a333eSShuo Chen  for (PollFdList::const_iterator pfd = pollfds_.begin();
524b7a333eSShuo Chen      pfd != pollfds_.end() && numEvents > 0; ++pfd)
534b7a333eSShuo Chen  {
544b7a333eSShuo Chen    if (pfd->revents > 0)
554b7a333eSShuo Chen    {
564b7a333eSShuo Chen      --numEvents;
574b7a333eSShuo Chen      ChannelMap::const_iterator ch = channels_.find(pfd->fd);
584b7a333eSShuo Chen      assert(ch != channels_.end());
594b7a333eSShuo Chen      Channel* channel = ch->second;
604b7a333eSShuo Chen      assert(channel->fd() == pfd->fd);
614b7a333eSShuo Chen      channel->set_revents(pfd->revents);
624b7a333eSShuo Chen      // pfd->revents = 0;
634b7a333eSShuo Chen      activeChannels->push_back(channel);
644b7a333eSShuo Chen    }
654b7a333eSShuo Chen  }
664b7a333eSShuo Chen}
674b7a333eSShuo Chen
684b7a333eSShuo Chenvoid Poller::updateChannel(Channel* channel)
694b7a333eSShuo Chen{
704b7a333eSShuo Chen  Poller::assertInLoopThread();
714b7a333eSShuo Chen  LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
724b7a333eSShuo Chen  if (channel->index() < 0)
734b7a333eSShuo Chen  {
744b7a333eSShuo Chen    // a new one, add to pollfds_
754b7a333eSShuo Chen    assert(channels_.find(channel->fd()) == channels_.end());
764b7a333eSShuo Chen    struct pollfd pfd;
774b7a333eSShuo Chen    pfd.fd = channel->fd();
784b7a333eSShuo Chen    pfd.events = static_cast<short>(channel->events());
794b7a333eSShuo Chen    pfd.revents = 0;
804b7a333eSShuo Chen    pollfds_.push_back(pfd);
814b7a333eSShuo Chen    int idx = static_cast<int>(pollfds_.size())-1;
824b7a333eSShuo Chen    channel->set_index(idx);
834b7a333eSShuo Chen    channels_[pfd.fd] = channel;
844b7a333eSShuo Chen  }
854b7a333eSShuo Chen  else
864b7a333eSShuo Chen  {
874b7a333eSShuo Chen    // update existing one
884b7a333eSShuo Chen    assert(channels_.find(channel->fd()) != channels_.end());
894b7a333eSShuo Chen    assert(channels_[channel->fd()] == channel);
904b7a333eSShuo Chen    int idx = channel->index();
914b7a333eSShuo Chen    assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
924b7a333eSShuo Chen    struct pollfd& pfd = pollfds_[idx];
934b7a333eSShuo Chen    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
944b7a333eSShuo Chen    pfd.events = static_cast<short>(channel->events());
954b7a333eSShuo Chen    if (pfd.events == Channel::kNoneEvent)
964b7a333eSShuo Chen    {
974b7a333eSShuo Chen      // ignore this pollfd
984b7a333eSShuo Chen      pfd.fd = -channel->fd()-1;
994b7a333eSShuo Chen    }
1004b7a333eSShuo Chen  }
1014b7a333eSShuo Chen}
1024b7a333eSShuo Chen
1034b7a333eSShuo Chenvoid Poller::removeChannel(Channel* channel)
1044b7a333eSShuo Chen{
1054b7a333eSShuo Chen  Poller::assertInLoopThread();
1064b7a333eSShuo Chen  LOG_TRACE << "fd = " << channel->fd();
1074b7a333eSShuo Chen  assert(channels_.find(channel->fd()) != channels_.end());
1084b7a333eSShuo Chen  assert(channels_[channel->fd()] == channel);
1094b7a333eSShuo Chen  assert(channel->events() == Channel::kNoneEvent);
1104b7a333eSShuo Chen  int idx = channel->index();
1114b7a333eSShuo Chen  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
1124b7a333eSShuo Chen  const struct pollfd& pfd = pollfds_[idx];
1134b7a333eSShuo Chen  (void)pfd;
1144b7a333eSShuo Chen  assert(pfd.fd == -channel->fd()-1 && pfd.events == Channel::kNoneEvent);
1154b7a333eSShuo Chen  size_t n = channels_.erase(channel->fd());
1164b7a333eSShuo Chen  (void)n;
1174b7a333eSShuo Chen  assert(n == 1);
1184b7a333eSShuo Chen  if (implicit_cast<size_t>(idx) == pollfds_.size()-1)
1194b7a333eSShuo Chen  {
1204b7a333eSShuo Chen    pollfds_.pop_back();
1214b7a333eSShuo Chen  }
1224b7a333eSShuo Chen  else
1234b7a333eSShuo Chen  {
1244b7a333eSShuo Chen    int channelAtEnd = pollfds_.back().fd;
1254b7a333eSShuo Chen    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
1264b7a333eSShuo Chen    if (channelAtEnd < 0)
1274b7a333eSShuo Chen    {
1284b7a333eSShuo Chen      channelAtEnd = -channelAtEnd-1;
1294b7a333eSShuo Chen    }
1304b7a333eSShuo Chen    channels_[channelAtEnd]->set_index(idx);
1314b7a333eSShuo Chen    pollfds_.pop_back();
1324b7a333eSShuo Chen  }
1334b7a333eSShuo Chen}
1344b7a333eSShuo Chen
135