Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
38dab040
Commit
38dab040
authored
Oct 13, 2020
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
event/Loop: add compile-time option to disable multithreading
Not for MPD, but for other applications which might want to copy its event loop, but do not need multi-threading.
parent
e9f6af61
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
81 additions
and
12 deletions
+81
-12
Loop.cxx
src/event/Loop.cxx
+35
-4
Loop.hxx
src/event/Loop.hxx
+45
-8
meson.build
src/event/meson.build
+1
-0
No files found.
src/event/Loop.cxx
View file @
38dab040
...
...
@@ -37,18 +37,27 @@ EventLoop::TimerCompare::operator()(const TimerEvent &a,
return
a
.
due
<
b
.
due
;
}
EventLoop
::
EventLoop
(
ThreadId
_thread
)
:
SocketMonitor
(
*
this
),
EventLoop
::
EventLoop
(
#ifdef HAVE_THREADED_EVENT_LOOP
ThreadId
_thread
#endif
)
:
#ifdef HAVE_THREADED_EVENT_LOOP
SocketMonitor
(
*
this
),
thread
(
_thread
),
/* if this instance is hosted by an EventThread (no ThreadId
known yet) then we're not yet alive until the thread is
started; for the main EventLoop instance, we assume it's
already alive, because nobody but EventThread will call
SetAlive() */
alive
(
!
_thread
.
IsNull
()),
quit
(
false
),
thread
(
_thread
)
#endif
quit
(
false
)
{
#ifdef HAVE_THREADED_EVENT_LOOP
SocketMonitor
::
Open
(
SocketDescriptor
(
wake_fd
.
Get
()));
#endif
}
EventLoop
::~
EventLoop
()
noexcept
...
...
@@ -83,13 +92,17 @@ EventLoop::Break() noexcept
if
(
quit
.
exchange
(
true
))
return
;
#ifdef HAVE_THREADED_EVENT_LOOP
wake_fd
.
Write
();
#endif
}
bool
EventLoop
::
Abandon
(
int
_fd
)
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
!
IsAlive
()
||
IsInside
());
#endif
return
poll_group
.
Abandon
(
_fd
);
}
...
...
@@ -97,7 +110,9 @@ EventLoop::Abandon(int _fd) noexcept
bool
EventLoop
::
RemoveFD
(
int
_fd
)
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
!
IsAlive
()
||
IsInside
());
#endif
return
poll_group
.
Remove
(
_fd
);
}
...
...
@@ -169,15 +184,19 @@ ExportTimeoutMS(Event::Duration timeout)
void
EventLoop
::
Run
()
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
if
(
thread
.
IsNull
())
thread
=
ThreadId
::
GetCurrent
();
#endif
assert
(
IsInside
());
assert
(
!
quit
);
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
alive
);
assert
(
busy
);
SocketMonitor
::
Schedule
(
SocketMonitor
::
READ
);
#endif
AtScopeExit
(
this
)
{
#ifdef HAVE_URING
/* make sure that the Uring::Manager gets destructed
...
...
@@ -188,7 +207,9 @@ EventLoop::Run() noexcept
uring_initialized
=
false
;
#endif
#ifdef HAVE_THREADED_EVENT_LOOP
SocketMonitor
::
Cancel
();
#endif
};
do
{
...
...
@@ -212,6 +233,7 @@ EventLoop::Run() noexcept
return
;
}
#ifdef HAVE_THREADED_EVENT_LOOP
/* try to handle DeferEvents without WakeFD
overhead */
{
...
...
@@ -225,6 +247,7 @@ EventLoop::Run() noexcept
new timeout */
continue
;
}
#endif
/* wait for new event */
...
...
@@ -240,10 +263,12 @@ EventLoop::Run() noexcept
now
=
std
::
chrono
::
steady_clock
::
now
();
#ifdef HAVE_THREADED_EVENT_LOOP
{
const
std
::
lock_guard
<
Mutex
>
lock
(
mutex
);
busy
=
true
;
}
#endif
/* invoke sockets */
while
(
!
ready_sockets
.
empty
()
&&
!
quit
)
{
...
...
@@ -254,11 +279,15 @@ EventLoop::Run() noexcept
}
}
while
(
!
quit
);
#ifdef HAVE_THREADED_EVENT_LOOP
#ifndef NDEBUG
assert
(
thread
.
IsInside
());
#endif
#endif
}
#ifdef HAVE_THREADED_EVENT_LOOP
void
EventLoop
::
AddDeferred
(
DeferEvent
&
d
)
noexcept
{
...
...
@@ -316,3 +345,5 @@ EventLoop::OnSocketReady([[maybe_unused]] unsigned flags) noexcept
return
true
;
}
#endif
src/event/Loop.hxx
View file @
38dab040
...
...
@@ -22,11 +22,15 @@
#include "Chrono.hxx"
#include "PollGroup.hxx"
#include "WakeFD.hxx"
#include "SocketMonitor.hxx"
#include "event/Features.h"
#include "util/Compiler.h"
#ifdef HAVE_THREADED_EVENT_LOOP
#include "WakeFD.hxx"
#include "thread/Id.hxx"
#include "thread/Mutex.hxx"
#
include "util/Compiler.h"
#
endif
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>
...
...
@@ -54,9 +58,14 @@ class DeferEvent;
*
* @see SocketMonitor, MultiSocketMonitor, TimerEvent, IdleEvent
*/
class
EventLoop
final
:
SocketMonitor
class
EventLoop
final
#ifdef HAVE_THREADED_EVENT_LOOP
:
SocketMonitor
#endif
{
#ifdef HAVE_THREADED_EVENT_LOOP
WakeFD
wake_fd
;
#endif
struct
TimerCompare
{
constexpr
bool
operator
()(
const
TimerEvent
&
a
,
...
...
@@ -76,6 +85,7 @@ class EventLoop final : SocketMonitor
boost
::
intrusive
::
constant_time_size
<
false
>>
;
IdleList
idle
;
#ifdef HAVE_THREADED_EVENT_LOOP
Mutex
mutex
;
using
DeferredList
=
...
...
@@ -83,6 +93,7 @@ class EventLoop final : SocketMonitor
boost
::
intrusive
::
base_hook
<
boost
::
intrusive
::
list_base_hook
<>>
,
boost
::
intrusive
::
constant_time_size
<
false
>>
;
DeferredList
deferred
;
#endif
using
ReadySocketList
=
boost
::
intrusive
::
list
<
SocketMonitor
,
...
...
@@ -103,6 +114,12 @@ class EventLoop final : SocketMonitor
Event
::
Clock
::
time_point
now
=
Event
::
Clock
::
now
();
#ifdef HAVE_THREADED_EVENT_LOOP
/**
* A reference to the thread that is currently inside Run().
*/
ThreadId
thread
=
ThreadId
::
Null
();
/**
* Is this #EventLoop alive, i.e. can events be scheduled?
* This is used by BlockingCall() to determine whether
...
...
@@ -110,6 +127,7 @@ class EventLoop final : SocketMonitor
* there's no #EventThread yet/anymore).
*/
bool
alive
;
#endif
std
::
atomic_bool
quit
;
...
...
@@ -119,6 +137,7 @@ class EventLoop final : SocketMonitor
*/
bool
again
;
#ifdef HAVE_THREADED_EVENT_LOOP
/**
* True when handling callbacks, false when waiting for I/O or
* timeout.
...
...
@@ -126,6 +145,7 @@ class EventLoop final : SocketMonitor
* Protected with #mutex.
*/
bool
busy
=
true
;
#endif
#ifdef HAVE_URING
bool
uring_initialized
=
false
;
...
...
@@ -133,18 +153,17 @@ class EventLoop final : SocketMonitor
PollGroup
poll_group
;
/**
* A reference to the thread that is currently inside Run().
*/
ThreadId
thread
=
ThreadId
::
Null
();
public
:
/**
* Throws on error.
*/
#ifdef HAVE_THREADED_EVENT_LOOP
explicit
EventLoop
(
ThreadId
_thread
);
EventLoop
()
:
EventLoop
(
ThreadId
::
GetCurrent
())
{}
#else
EventLoop
();
#endif
~
EventLoop
()
noexcept
;
...
...
@@ -152,7 +171,9 @@ public:
* A caching wrapper for Event::Clock::now().
*/
auto
GetTime
()
const
{
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
IsInside
());
#endif
return
now
;
}
...
...
@@ -170,13 +191,17 @@ public:
void
Break
()
noexcept
;
bool
AddFD
(
int
_fd
,
unsigned
flags
,
SocketMonitor
&
m
)
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
!
IsAlive
()
||
IsInside
());
#endif
return
poll_group
.
Add
(
_fd
,
flags
,
&
m
);
}
bool
ModifyFD
(
int
_fd
,
unsigned
flags
,
SocketMonitor
&
m
)
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
assert
(
!
IsAlive
()
||
IsInside
());
#endif
return
poll_group
.
Modify
(
_fd
,
flags
,
&
m
);
}
...
...
@@ -195,6 +220,7 @@ public:
void
AddTimer
(
TimerEvent
&
t
,
Event
::
Duration
d
)
noexcept
;
#ifdef HAVE_THREADED_EVENT_LOOP
/**
* Schedule a call to DeferEvent::RunDeferred().
*
...
...
@@ -209,6 +235,7 @@ public:
* This method is thread-safe.
*/
void
RemoveDeferred
(
DeferEvent
&
d
)
noexcept
;
#endif
/**
* The main function of this class. It will loop until
...
...
@@ -217,12 +244,14 @@ public:
void
Run
()
noexcept
;
private
:
#ifdef HAVE_THREADED_EVENT_LOOP
/**
* Invoke all pending DeferEvents.
*
* Caller must lock the mutex.
*/
void
HandleDeferred
()
noexcept
;
#endif
/**
* Invoke all expired #TimerEvent instances and return the
...
...
@@ -231,9 +260,12 @@ private:
*/
Event
::
Duration
HandleTimers
()
noexcept
;
#ifdef HAVE_THREADED_EVENT_LOOP
bool
OnSocketReady
(
unsigned
flags
)
noexcept
override
;
#endif
public
:
#ifdef HAVE_THREADED_EVENT_LOOP
void
SetAlive
(
bool
_alive
)
noexcept
{
alive
=
_alive
;
}
...
...
@@ -241,13 +273,18 @@ public:
bool
IsAlive
()
const
noexcept
{
return
alive
;
}
#endif
/**
* Are we currently running inside this EventLoop's thread?
*/
gcc_pure
bool
IsInside
()
const
noexcept
{
#ifdef HAVE_THREADED_EVENT_LOOP
return
thread
.
IsInside
();
#else
return
true
;
#endif
}
};
...
...
src/event/meson.build
View file @
38dab040
...
...
@@ -2,6 +2,7 @@ event_features = configuration_data()
event_features.set('USE_EVENTFD', is_linux and get_option('eventfd'))
event_features.set('USE_SIGNALFD', is_linux and get_option('signalfd'))
event_features.set('USE_EPOLL', is_linux and get_option('epoll'))
event_features.set('HAVE_THREADED_EVENT_LOOP', true)
configure_file(output: 'Features.h', configuration: event_features)
event_sources = []
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment