MPD  0.20.6
MultiSocketMonitor.hxx
Go to the documentation of this file.
1 /*
2  * Copyright 2003-2017 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef MPD_MULTI_SOCKET_MONITOR_HXX
21 #define MPD_MULTI_SOCKET_MONITOR_HXX
22 
23 #include "check.h"
24 #include "IdleMonitor.hxx"
25 #include "TimeoutMonitor.hxx"
26 #include "SocketMonitor.hxx"
27 #include "Compiler.h"
28 
29 #include <forward_list>
30 #include <iterator>
31 
32 #include <assert.h>
33 
34 #ifdef WIN32
35 /* ERROR is a WIN32 macro that poisons our namespace; this is a kludge
36  to allow us to use it anyway */
37 #ifdef ERROR
38 #undef ERROR
39 #endif
40 #endif
41 
42 #ifndef WIN32
43 struct pollfd;
44 #endif
45 
46 class EventLoop;
47 
55 {
56  class SingleFD final : public SocketMonitor {
57  MultiSocketMonitor &multi;
58 
59  unsigned revents;
60 
61  public:
62  SingleFD(MultiSocketMonitor &_multi, int _fd, unsigned events)
63  :SocketMonitor(_fd, _multi.GetEventLoop()),
64  multi(_multi), revents(0) {
65  Schedule(events);
66  }
67 
68  int GetFD() const {
69  return SocketMonitor::Get();
70  }
71 
72  unsigned GetEvents() const {
74  }
75 
76  void SetEvents(unsigned _events) {
77  revents &= _events;
78  SocketMonitor::Schedule(_events);
79  }
80 
81  unsigned GetReturnedEvents() const {
82  return revents;
83  }
84 
85  void ClearReturnedEvents() {
86  revents = 0;
87  }
88 
89  protected:
90  virtual bool OnSocketReady(unsigned flags) override {
91  revents = flags;
92  multi.SetReady();
93  return true;
94  }
95  };
96 
97  friend class SingleFD;
98 
102  bool ready = false;
103 
111  bool refresh;
112 
113  std::forward_list<SingleFD> fds;
114 
115 public:
116  static constexpr unsigned READ = SocketMonitor::READ;
117  static constexpr unsigned WRITE = SocketMonitor::WRITE;
118  static constexpr unsigned ERROR = SocketMonitor::ERROR;
119  static constexpr unsigned HANGUP = SocketMonitor::HANGUP;
120 
122 
124 
140  void Reset();
141 
147  refresh = true;
149  }
150 
156  void AddSocket(int fd, unsigned events) {
157  fds.emplace_front(*this, fd, events);
158  }
159 
165  void ClearSocketList();
166 
175  template<typename E>
176  void UpdateSocketList(E &&e) {
177  for (auto prev = fds.before_begin(), end = fds.end(),
178  i = std::next(prev);
179  i != end; i = std::next(prev)) {
180  assert(i->GetEvents() != 0);
181 
182  unsigned events = e(i->GetFD());
183  if (events != 0) {
184  i->SetEvents(events);
185  prev = i;
186  } else {
187  fds.erase_after(prev);
188  }
189  }
190  }
191 
192 #ifndef WIN32
193 
199  void ReplaceSocketList(pollfd *pfds, unsigned n);
200 #endif
201 
202 protected:
210  virtual std::chrono::steady_clock::duration PrepareSockets() = 0;
211 
216  virtual void DispatchSockets() = 0;
217 
218 private:
219  void SetReady() {
220  ready = true;
222  }
223 
224  void Prepare();
225 
226  virtual void OnTimeout() final {
227  SetReady();
229  }
230 
231  virtual void OnIdle() final;
232 };
233 
234 #endif
static constexpr unsigned WRITE
void InvalidateSockets()
Invalidate the socket list.
unsigned GetScheduledFlags() const
int Get() const
static constexpr unsigned READ
void AddSocket(int fd, unsigned events)
Add one socket to the list of monitored sockets.
This class monitors a timeout.
An event that runs when the EventLoop has become idle, before waiting for more events.
Definition: IdleMonitor.hxx:35
An event loop that polls for events on file/socket descriptors.
Definition: Loop.hxx:51
void UpdateSocketList(E &&e)
Update the known sockets by invoking the given function for each one; its return value is the events ...
void Schedule(unsigned flags)
void ClearSocketList()
Remove all sockets.
void Reset()
Clear the socket list and disable all EventLoop registrations.
void ReplaceSocketList(pollfd *pfds, unsigned n)
Replace the socket list with the given file descriptors.
static constexpr unsigned ERROR
virtual std::chrono::steady_clock::duration PrepareSockets()=0
Override this method and update the socket registrations.
Monitor events on a socket.
static constexpr unsigned HANGUP
MultiSocketMonitor(EventLoop &_loop)
static constexpr unsigned READ
EventLoop & GetEventLoop() const
Definition: IdleMonitor.hxx:55
virtual void DispatchSockets()=0
At least one socket is ready or the timeout has expired.
static constexpr unsigned WRITE
void Schedule()
static constexpr unsigned HANGUP
Similar to SocketMonitor, but monitors multiple sockets.
static constexpr unsigned ERROR
int e
Definition: Log.hxx:115