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
863f4d83
Commit
863f4d83
authored
Jun 17, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
util/BindMethod: new utility class for callbacks
Replaces the old BoundMethod template.
parent
bdd0c368
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
206 additions
and
92 deletions
+206
-92
Makefile.am
Makefile.am
+1
-1
Instance.hxx
src/Instance.hxx
+2
-2
Partition.cxx
src/Partition.cxx
+1
-1
Partition.hxx
src/Partition.hxx
+1
-1
MaskMonitor.cxx
src/event/MaskMonitor.cxx
+1
-1
MaskMonitor.hxx
src/event/MaskMonitor.hxx
+7
-24
BindMethod.hxx
src/util/BindMethod.hxx
+193
-0
BoundMethod.hxx
src/util/BoundMethod.hxx
+0
-62
No files found.
Makefile.am
View file @
863f4d83
...
...
@@ -391,7 +391,7 @@ endif
libutil_a_SOURCES
=
\
src/util/RuntimeError.hxx
\
src/util/Macros.hxx
\
src/util/B
ou
ndMethod.hxx
\
src/util/B
i
ndMethod.hxx
\
src/util/Cast.hxx
\
src/util/Clamp.hxx
\
src/util/DeleteDisposer.hxx
\
...
...
src/Instance.hxx
View file @
863f4d83
...
...
@@ -65,7 +65,7 @@ struct Instance final
public
NeighborListener
#endif
{
CallbackMaskMonitor
<
Instance
>
idle_monitor
;
MaskMonitor
idle_monitor
;
#ifdef ENABLE_NEIGHBOR_PLUGINS
NeighborGlue
*
neighbors
;
...
...
@@ -90,7 +90,7 @@ struct Instance final
StateFile
*
state_file
;
Instance
()
:
idle_monitor
(
event_loop
,
*
this
,
&
Instance
::
OnIdle
)
{}
:
idle_monitor
(
event_loop
,
BIND_THIS_METHOD
(
OnIdle
)
)
{}
/**
* Initiate shutdown. Wrapper for EventLoop::Break().
...
...
src/Partition.cxx
View file @
863f4d83
...
...
@@ -29,7 +29,7 @@ Partition::Partition(Instance &_instance,
unsigned
buffer_chunks
,
unsigned
buffered_before_play
)
:
instance
(
_instance
),
global_events
(
instance
.
event_loop
,
*
this
,
&
Partition
::
OnGlobalEvent
),
global_events
(
instance
.
event_loop
,
BIND_THIS_METHOD
(
OnGlobalEvent
)
),
playlist
(
max_length
,
*
this
),
outputs
(
*
this
),
pc
(
*
this
,
outputs
,
buffer_chunks
,
buffered_before_play
)
...
...
src/Partition.hxx
View file @
863f4d83
...
...
@@ -44,7 +44,7 @@ struct Partition final : QueueListener, PlayerListener, MixerListener {
Instance
&
instance
;
CallbackMaskMonitor
<
Partition
>
global_events
;
MaskMonitor
global_events
;
struct
playlist
playlist
;
...
...
src/event/MaskMonitor.cxx
View file @
863f4d83
...
...
@@ -32,5 +32,5 @@ MaskMonitor::RunDeferred()
{
const
unsigned
mask
=
pending_mask
.
exchange
(
0
);
if
(
mask
!=
0
)
HandleMas
k
(
mask
);
callbac
k
(
mask
);
}
src/event/MaskMonitor.hxx
View file @
863f4d83
...
...
@@ -22,7 +22,7 @@
#include "check.h"
#include "DeferredMonitor.hxx"
#include "util/B
ou
ndMethod.hxx"
#include "util/B
i
ndMethod.hxx"
#include <atomic>
...
...
@@ -32,12 +32,15 @@
*
* This class is thread-safe.
*/
class
MaskMonitor
:
DeferredMonitor
{
class
MaskMonitor
final
:
DeferredMonitor
{
typedef
BoundMethod
<
void
(
unsigned
)
>
Callback
;
const
Callback
callback
;
std
::
atomic_uint
pending_mask
;
public
:
explicit
MaskMonitor
(
EventLoop
&
_loop
)
:
DeferredMonitor
(
_loop
),
pending_mask
(
0
)
{}
MaskMonitor
(
EventLoop
&
_loop
,
Callback
_callback
)
:
DeferredMonitor
(
_loop
),
callback
(
_callback
),
pending_mask
(
0
)
{}
using
DeferredMonitor
::
GetEventLoop
;
using
DeferredMonitor
::
Cancel
;
...
...
@@ -45,28 +48,8 @@ public:
void
OrMask
(
unsigned
new_mask
);
protected
:
virtual
void
HandleMask
(
unsigned
mask
)
=
0
;
/* virtual methode from class DeferredMonitor */
void
RunDeferred
()
override
;
};
/**
* A variant of #MaskMonitor which invokes a bound method.
*/
template
<
typename
T
>
class
CallbackMaskMonitor
final
:
public
MaskMonitor
{
BoundMethod
<
T
,
void
,
unsigned
>
callback
;
public
:
template
<
typename
...
Args
>
explicit
CallbackMaskMonitor
(
EventLoop
&
_loop
,
Args
&&
...
args
)
:
MaskMonitor
(
_loop
),
callback
(
std
::
forward
<
Args
>
(
args
)...)
{}
protected
:
void
HandleMask
(
unsigned
mask
)
override
{
callback
(
mask
);
}
};
#endif
src/util/BindMethod.hxx
0 → 100644
View file @
863f4d83
/*
* Copyright (C) 2016 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BIND_METHOD_HXX
#define BIND_METHOD_HXX
#include <type_traits>
#include <utility>
/**
* This object stores a function pointer wrapping a method, and a
* reference to an instance of the method's class. It can be used to
* wrap instance methods as callback functions.
*
* @param S the plain function signature type
*/
template
<
typename
S
=
void
()
>
class
BoundMethod
;
template
<
typename
R
,
typename
...
Args
>
class
BoundMethod
<
R
(
Args
...)
>
{
typedef
R
(
*
function_pointer
)(
void
*
instance
,
Args
...
args
);
void
*
instance_
;
function_pointer
function
;
public
:
BoundMethod
()
=
default
;
constexpr
BoundMethod
(
void
*
_instance
,
function_pointer
_function
)
:
instance_
(
_instance
),
function
(
_function
)
{}
R
operator
()(
Args
...
args
)
const
{
return
function
(
instance_
,
std
::
forward
<
Args
>
(
args
)...);
}
};
namespace
BindMethodDetail
{
/**
* Helper class which converts a signature type to a method pointer
* type.
*
* @param T the wrapped class
* @param S the function signature type (plain, without instance
* pointer)
*/
template
<
typename
T
,
typename
S
>
struct
MethodWithSignature
;
template
<
typename
T
,
typename
R
,
typename
...
Args
>
struct
MethodWithSignature
<
T
,
R
(
Args
...)
>
{
typedef
R
(
T
::*
method_pointer
)(
Args
...);
};
/**
* Helper class which introspects a method pointer type.
*
* @param M the method pointer type
*/
template
<
typename
M
>
struct
MethodSignatureHelper
;
template
<
typename
R
,
typename
T
,
typename
...
Args
>
struct
MethodSignatureHelper
<
R
(
T
::*
)(
Args
...)
>
{
/**
* The class which contains the given method (signature).
*/
typedef
T
class_type
;
/**
* A function type which describes the "plain" function
* signature.
*/
typedef
R
plain_signature
(
Args
...);
};
/**
* Helper class which converts a plain function signature type to a
* wrapper function pointer type.
*/
template
<
typename
S
>
struct
MethodWrapperWithSignature
;
template
<
typename
R
,
typename
...
Args
>
struct
MethodWrapperWithSignature
<
R
(
Args
...)
>
{
typedef
R
(
*
function_pointer
)(
void
*
instance
,
Args
...);
};
/**
* Generate a wrapper function. Helper class for
* #BindMethodWrapperGenerator.
*
* @param T the containing class
* @param M the method pointer type
* @param method the method pointer
* @param R the return type
* @param Args the method arguments
*/
template
<
typename
T
,
typename
M
,
M
method
,
typename
R
,
typename
...
Args
>
struct
BindMethodWrapperGenerator2
{
static
R
Invoke
(
void
*
_instance
,
Args
...
args
)
{
auto
&
t
=
*
(
T
*
)
_instance
;
return
(
t
.
*
method
)(
std
::
forward
<
Args
>
(
args
)...);
}
};
/**
* Generate a wrapper function.
*
* @param T the containing class
* @param M the method pointer type
* @param method the method pointer
* @param S the plain function signature type
*/
template
<
typename
T
,
typename
M
,
M
method
,
typename
S
>
struct
BindMethodWrapperGenerator
;
template
<
typename
T
,
typename
M
,
M
method
,
typename
R
,
typename
...
Args
>
struct
BindMethodWrapperGenerator
<
T
,
M
,
method
,
R
(
Args
...)
>
:
BindMethodWrapperGenerator2
<
T
,
M
,
method
,
R
,
Args
...
>
{
};
template
<
typename
T
,
typename
S
,
typename
MethodWithSignature
<
T
,
S
>::
method_pointer
method
>
typename
MethodWrapperWithSignature
<
S
>::
function_pointer
MakeBindMethodWrapper
()
{
return
BindMethodWrapperGenerator
<
T
,
typename
MethodWithSignature
<
T
,
S
>::
method_pointer
,
method
,
S
>::
Invoke
;
}
}
/* namespace BindMethodDetail */
/**
* Construct a #BoundMethod instance.
*
* @param T the containing class
* @param S the plain function signature type
* @param method the method pointer
* @param instance the instance of #T to be bound
*/
template
<
typename
T
,
typename
S
,
typename
BindMethodDetail
::
MethodWithSignature
<
T
,
S
>::
method_pointer
method
>
constexpr
BoundMethod
<
S
>
BindMethod
(
T
&
_instance
)
{
return
BoundMethod
<
S
>
(
&
_instance
,
BindMethodDetail
::
MakeBindMethodWrapper
<
T
,
S
,
method
>
());
}
/**
* Shortcut macro which takes an instance and a method pointer and
* constructs a #BoundMethod instance.
*/
#define BIND_METHOD(instance, method) \
BindMethod<typename BindMethodDetail::MethodSignatureHelper<decltype(method)>::class_type, \
typename BindMethodDetail::MethodSignatureHelper<decltype(method)>::plain_signature, \
method>(instance)
/**
* Shortcut wrapper for BIND_METHOD() which assumes "*this" is the
* instance to be bound.
*/
#define BIND_THIS_METHOD(method) BIND_METHOD(*this, &std::remove_reference<decltype(*this)>::type::method)
#endif
src/util/BoundMethod.hxx
deleted
100644 → 0
View file @
bdd0c368
/*
* Copyright (C) 2016 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BOUND_METHOD_HXX
#define BOUND_METHOD_HXX
#include <utility>
/**
* This class can invoke a method of a given object. To do this, it
* stores a pointer to the member function and a reference to the
* object.
*
* This is a utility to build callbacks.
*
* @param T the class whose method is going to be invoked
* @param R the method's return type
* @param Args argument types
*/
template
<
typename
T
,
typename
R
,
typename
...
Args
>
class
BoundMethod
final
{
T
&
instance
;
R
(
T
::*
method
)(
Args
...
args
);
public
:
explicit
constexpr
BoundMethod
(
T
&
_instance
,
R
(
T
::*
_method
)(
Args
...
args
))
:
instance
(
_instance
),
method
(
_method
)
{}
template
<
typename
...
Args2
>
R
operator
()(
Args2
&&
...
args
)
{
return
(
instance
.
*
method
)(
std
::
forward
<
Args2
>
(
args
)...);
}
};
#endif
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