MPD  0.20.18
Loop.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_EVENT_LOOP_HXX
21 #define MPD_EVENT_LOOP_HXX
22 
23 #include "check.h"
24 #include "thread/Id.hxx"
25 #include "Compiler.h"
26 
27 #include "PollGroup.hxx"
28 #include "thread/Mutex.hxx"
29 #include "WakeFD.hxx"
30 #include "SocketMonitor.hxx"
31 
32 #include <chrono>
33 #include <atomic>
34 #include <list>
35 #include <set>
36 
37 class TimeoutMonitor;
38 class IdleMonitor;
39 class DeferredMonitor;
40 
41 #include <assert.h>
42 
52 class EventLoop final : SocketMonitor
53 {
54  struct TimerRecord {
59  const std::chrono::steady_clock::time_point due;
60 
61  TimeoutMonitor &timer;
62 
63  constexpr TimerRecord(TimeoutMonitor &_timer,
64  std::chrono::steady_clock::time_point _due)
65  :due(_due), timer(_timer) {}
66 
67  bool operator<(const TimerRecord &other) const {
68  return due < other.due;
69  }
70 
71  bool IsDue(std::chrono::steady_clock::time_point _now) const {
72  return _now >= due;
73  }
74  };
75 
76  WakeFD wake_fd;
77 
78  std::multiset<TimerRecord> timers;
79  std::list<IdleMonitor *> idle;
80 
81  Mutex mutex;
82  std::list<DeferredMonitor *> deferred;
83 
84  std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
85 
86  std::atomic_bool quit;
87 
92  bool again;
93 
100  bool busy = true;
101 
102 #ifndef NDEBUG
103 
107  bool virgin = true;
108 #endif
109 
110  PollGroup poll_group;
111  PollResult poll_result;
112 
116  ThreadId thread = ThreadId::Null();
117 
118 public:
119  EventLoop();
120  ~EventLoop();
121 
125  std::chrono::steady_clock::time_point GetTime() const {
126  assert(IsInside());
127 
128  return now;
129  }
130 
136  void Break();
137 
138  bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
139  assert(thread.IsNull() || thread.IsInside());
140 
141  return poll_group.Add(_fd, flags, &m);
142  }
143 
144  bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m) {
145  assert(IsInside());
146 
147  return poll_group.Modify(_fd, flags, &m);
148  }
149 
155  bool Abandon(int fd, SocketMonitor &m);
156 
157  bool RemoveFD(int fd, SocketMonitor &m);
158 
159  void AddIdle(IdleMonitor &i);
160  void RemoveIdle(IdleMonitor &i);
161 
162  void AddTimer(TimeoutMonitor &t,
163  std::chrono::steady_clock::duration d);
164  void CancelTimer(TimeoutMonitor &t);
165 
171  void AddDeferred(DeferredMonitor &d);
172 
180 
185  void Run();
186 
187 private:
193  void HandleDeferred();
194 
195  virtual bool OnSocketReady(unsigned flags) override;
196 
197 public:
198 
202  gcc_pure
203  bool IsInside() const noexcept {
204  assert(!thread.IsNull());
205 
206  return thread.IsInside();
207  }
208 
209 #ifndef NDEBUG
210  gcc_pure
211  bool IsInsideOrVirgin() const noexcept {
212  return virgin || IsInside();
213  }
214 #endif
215 
222  gcc_pure
223  bool IsInsideOrNull() const noexcept {
224  return thread.IsNull() || thread.IsInside();
225  }
226 };
227 
228 #endif /* MAIN_NOTIFY_H */
gcc_pure bool IsInsideOrVirgin() const noexcept
Definition: Loop.hxx:211
This class monitors a timeout.
static constexpr ThreadId Null() noexcept
Definition: Id.hxx:55
An event that runs when the EventLoop has become idle, before waiting for more events.
Definition: IdleMonitor.hxx:35
A low-level identification for a thread.
Definition: Id.hxx:36
std::chrono::steady_clock::time_point GetTime() const
A caching wrapper for std::chrono::steady_clock::now().
Definition: Loop.hxx:125
void CancelTimer(TimeoutMonitor &t)
An event loop that polls for events on file/socket descriptors.
Definition: Loop.hxx:52
void Break()
Stop execution of this EventLoop at the next chance.
void AddIdle(IdleMonitor &i)
void RemoveIdle(IdleMonitor &i)
gcc_pure bool IsInsideOrNull() const noexcept
Like IsInside(), but also returns true if the thread has already ended (or was not started yet)...
Definition: Loop.hxx:223
Definition: Mutex.hxx:43
Defer execution of an event into an EventLoop.
bool AddFD(int _fd, unsigned flags, SocketMonitor &m)
Definition: Loop.hxx:138
void Abandon()
Somebody has closed the socket.
bool IsInside() const noexcept
Check if this thread is the current thread.
Definition: Id.hxx:94
gcc_pure bool IsNull() const noexcept
Definition: Id.hxx:64
void Run()
The main function of this class.
gcc_pure bool IsInside() const noexcept
Are we currently running inside this EventLoop&#39;s thread?
Definition: Loop.hxx:203
Monitor events on a socket.
void AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d)
void AddDeferred(DeferredMonitor &d)
Schedule a call to DeferredMonitor::RunDeferred().
#define WakeFD
Definition: WakeFD.hxx:32
bool RemoveFD(int fd, SocketMonitor &m)
bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m)
Definition: Loop.hxx:144
#define gcc_pure
Definition: Compiler.h:116
void RemoveDeferred(DeferredMonitor &d)
Cancel a pending call to DeferredMonitor::RunDeferred().