s06-s05-Poller.cc.diff revision 048f6023
1048f6023SShuo Chen // excerpts from http://code.google.com/p/muduo/
2048f6023SShuo Chen //
3048f6023SShuo Chen // Use of this source code is governed by a BSD-style license
4048f6023SShuo Chen // that can be found in the License file.
5048f6023SShuo Chen //
6048f6023SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
7048f6023SShuo Chen 
8048f6023SShuo Chen #include "Poller.h"
9048f6023SShuo Chen 
10048f6023SShuo Chen #include "Channel.h"
11048f6023SShuo Chen #include "logging/Logging.h"
12048f6023SShuo Chen 
13048f6023SShuo Chen #include <assert.h>
14048f6023SShuo Chen #include <poll.h>
15048f6023SShuo Chen 
16048f6023SShuo Chen using namespace muduo;
17048f6023SShuo Chen 
18048f6023SShuo Chen Poller::Poller(EventLoop* loop)
19048f6023SShuo Chen   : ownerLoop_(loop)
20048f6023SShuo Chen {
21048f6023SShuo Chen }
22048f6023SShuo Chen 
23048f6023SShuo Chen Poller::~Poller()
24048f6023SShuo Chen {
25048f6023SShuo Chen }
26048f6023SShuo Chen 
27048f6023SShuo Chen Timestamp Poller::poll(int timeoutMs, ChannelList* activeChannels)
28048f6023SShuo Chen {
29048f6023SShuo Chen   // XXX pollfds_ shouldn't change
30048f6023SShuo Chen   int numEvents = ::poll(&*pollfds_.begin(), pollfds_.size(), timeoutMs);
31048f6023SShuo Chen   Timestamp now(Timestamp::now());
32048f6023SShuo Chen   if (numEvents > 0)
33048f6023SShuo Chen   {
34048f6023SShuo Chen     LOG_TRACE << numEvents << " events happended";
35048f6023SShuo Chen     fillActiveChannels(numEvents, activeChannels);
36048f6023SShuo Chen   }
37048f6023SShuo Chen   else if (numEvents == 0)
38048f6023SShuo Chen   {
39048f6023SShuo Chen     LOG_TRACE << " nothing happended";
40048f6023SShuo Chen   }
41048f6023SShuo Chen   else
42048f6023SShuo Chen   {
43048f6023SShuo Chen     LOG_SYSERR << "Poller::poll()";
44048f6023SShuo Chen   }
45048f6023SShuo Chen   return now;
46048f6023SShuo Chen }
47048f6023SShuo Chen 
48048f6023SShuo Chen void Poller::fillActiveChannels(int numEvents,
49048f6023SShuo Chen                                 ChannelList* activeChannels) const
50048f6023SShuo Chen {
51048f6023SShuo Chen   for (PollFdList::const_iterator pfd = pollfds_.begin();
52048f6023SShuo Chen       pfd != pollfds_.end() && numEvents > 0; ++pfd)
53048f6023SShuo Chen   {
54048f6023SShuo Chen     if (pfd->revents > 0)
55048f6023SShuo Chen     {
56048f6023SShuo Chen       --numEvents;
57048f6023SShuo Chen       ChannelMap::const_iterator ch = channels_.find(pfd->fd);
58048f6023SShuo Chen       assert(ch != channels_.end());
59048f6023SShuo Chen       Channel* channel = ch->second;
60048f6023SShuo Chen       assert(channel->fd() == pfd->fd);
61048f6023SShuo Chen       channel->set_revents(pfd->revents);
62048f6023SShuo Chen       // pfd->revents = 0;
63048f6023SShuo Chen       activeChannels->push_back(channel);
64048f6023SShuo Chen     }
65048f6023SShuo Chen   }
66048f6023SShuo Chen }
67048f6023SShuo Chen 
68048f6023SShuo Chen void Poller::updateChannel(Channel* channel)
69048f6023SShuo Chen {
70048f6023SShuo Chen   assertInLoopThread();
71048f6023SShuo Chen   LOG_TRACE << "fd = " << channel->fd() << " events = " << channel->events();
72048f6023SShuo Chen   if (channel->index() < 0)
73048f6023SShuo Chen   {
74048f6023SShuo Chen     // a new one, add to pollfds_
75048f6023SShuo Chen     assert(channels_.find(channel->fd()) == channels_.end());
76048f6023SShuo Chen     struct pollfd pfd;
77048f6023SShuo Chen     pfd.fd = channel->fd();
78048f6023SShuo Chen     pfd.events = static_cast<short>(channel->events());
79048f6023SShuo Chen     pfd.revents = 0;
80048f6023SShuo Chen     pollfds_.push_back(pfd);
81048f6023SShuo Chen     int idx = static_cast<int>(pollfds_.size())-1;
82048f6023SShuo Chen     channel->set_index(idx);
83048f6023SShuo Chen     channels_[pfd.fd] = channel;
84048f6023SShuo Chen   }
85048f6023SShuo Chen   else
86048f6023SShuo Chen   {
87048f6023SShuo Chen     // update existing one
88048f6023SShuo Chen     assert(channels_.find(channel->fd()) != channels_.end());
89048f6023SShuo Chen     assert(channels_[channel->fd()] == channel);
90048f6023SShuo Chen     int idx = channel->index();
91048f6023SShuo Chen     assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
92048f6023SShuo Chen     struct pollfd& pfd = pollfds_[idx];
93048f6023SShuo Chen!    assert(pfd.fd == channel->fd() || pfd.fd == -channel->fd()-1);
94048f6023SShuo Chen     pfd.events = static_cast<short>(channel->events());
95048f6023SShuo Chen     pfd.revents = 0;
96048f6023SShuo Chen     if (channel->isNoneEvent())
97048f6023SShuo Chen     {
98048f6023SShuo Chen       // ignore this pollfd
99048f6023SShuo Chen!      pfd.fd = -channel->fd()-1;
100048f6023SShuo Chen     }
101048f6023SShuo Chen   }
102048f6023SShuo Chen }
103048f6023SShuo Chen 
104048f6023SShuo Chen+void Poller::removeChannel(Channel* channel)
105048f6023SShuo Chen+{
106048f6023SShuo Chen+  assertInLoopThread();
107048f6023SShuo Chen+  LOG_TRACE << "fd = " << channel->fd();
108048f6023SShuo Chen+  assert(channels_.find(channel->fd()) != channels_.end());
109048f6023SShuo Chen+  assert(channels_[channel->fd()] == channel);
110048f6023SShuo Chen+  assert(channel->isNoneEvent());
111048f6023SShuo Chen+  int idx = channel->index();
112048f6023SShuo Chen+  assert(0 <= idx && idx < static_cast<int>(pollfds_.size()));
113048f6023SShuo Chen+  const struct pollfd& pfd = pollfds_[idx]; (void)pfd;
114048f6023SShuo Chen+  assert(pfd.fd == -channel->fd()-1 && pfd.events == channel->events());
115048f6023SShuo Chen+  size_t n = channels_.erase(channel->fd());
116048f6023SShuo Chen+  assert(n == 1); (void)n;
117048f6023SShuo Chen+  if (implicit_cast<size_t>(idx) == pollfds_.size()-1)
118048f6023SShuo Chen+  {
119048f6023SShuo Chen+    pollfds_.pop_back();
120048f6023SShuo Chen+  }
121048f6023SShuo Chen+  else
122048f6023SShuo Chen+  {
123048f6023SShuo Chen+    int channelAtEnd = pollfds_.back().fd;
124048f6023SShuo Chen+    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
125048f6023SShuo Chen+    if (channelAtEnd < 0)
126048f6023SShuo Chen+    {
127048f6023SShuo Chen+      channelAtEnd = -channelAtEnd-1;
128048f6023SShuo Chen+    }
129048f6023SShuo Chen+    channels_[channelAtEnd]->set_index(idx);
130048f6023SShuo Chen+    pollfds_.pop_back();
131048f6023SShuo Chen+  }
132048f6023SShuo Chen+}
133048f6023SShuo Chen+
134