Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
9a414758
Commit
9a414758
authored
Sep 21, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for heap-allocated callbacks
parent
9e060c37
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
40 additions
and
13 deletions
+40
-13
libcaf_core/caf/callback.hpp
libcaf_core/caf/callback.hpp
+40
-13
No files found.
libcaf_core/caf/callback.hpp
View file @
9a414758
...
@@ -19,38 +19,47 @@
...
@@ -19,38 +19,47 @@
#pragma once
#pragma once
#include "caf/config.hpp"
#include "caf/config.hpp"
#include "caf/error.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/error.hpp"
// The class `callback` intentionally has no virtual destructor, because
#include <memory>
// the lifetime of callback objects is never managed via base pointers.
CAF_PUSH_NON_VIRTUAL_DTOR_WARNING
namespace
caf
{
namespace
caf
{
/// Describes a simple callback, usually implemented via lambda expression.
/// Describes a simple callback, usually implemented via lambda expression.
/// Callbacks are used as "type-safe function objects" wherever an interface
/// Callbacks are used as "type-safe function objects" wherever an interface
/// requires dynamic dispatching. The alternative would be to store the lambda
/// requires dynamic dispatching. The alternative would be to store the lambda
/// in a `std::function`, which adds another layer of indirection and
/// in a `std::function`, which adds another layer of indirection and
always
/// requires a heap allocation. With the callback implementation of CAF,
/// requires a heap allocation. With the callback implementation of CAF,
the
///
the object remains on the stack and does not cause more overhead
///
object may remains on the stack and do not cause more overhead than
///
than
necessary.
/// necessary.
template
<
class
Signature
>
template
<
class
Signature
>
class
callback
;
class
callback
;
template
<
class
Result
,
class
...
Ts
>
template
<
class
Result
,
class
...
Ts
>
class
callback
<
Result
(
Ts
...)
>
{
class
callback
<
Result
(
Ts
...)
>
{
public:
public:
virtual
~
callback
()
{
// nop
}
virtual
Result
operator
()(
Ts
...)
=
0
;
virtual
Result
operator
()(
Ts
...)
=
0
;
};
};
/// Smart pointer type for heap-allocated callbacks with unique ownership.
template
<
class
Signature
>
using
unique_callback_ptr
=
std
::
unique_ptr
<
callback
<
Signature
>>
;
/// Smart pointer type for heap-allocated callbacks with shared ownership.
template
<
class
Signature
>
using
shared_callback_ptr
=
std
::
shared_ptr
<
callback
<
Signature
>>
;
/// Utility class for wrapping a function object of type `F`.
/// Utility class for wrapping a function object of type `F`.
template
<
class
F
,
class
Signature
>
template
<
class
F
,
class
Signature
>
class
callback_impl
;
class
callback_impl
;
template
<
class
F
,
class
Result
,
class
...
Ts
>
template
<
class
F
,
class
Result
,
class
...
Ts
>
class
callback_impl
<
F
,
Result
(
Ts
...)
>
:
public
callback
<
Result
(
Ts
...)
>
{
class
callback_impl
<
F
,
Result
(
Ts
...)
>
final
:
public
callback
<
Result
(
Ts
...)
>
{
public:
public:
callback_impl
(
F
&&
f
)
:
f_
(
std
::
move
(
f
))
{
callback_impl
(
F
&&
f
)
:
f_
(
std
::
move
(
f
))
{
// nop
// nop
...
@@ -68,7 +77,7 @@ private:
...
@@ -68,7 +77,7 @@ private:
F
f_
;
F
f_
;
};
};
///
Creates a ::callback from the function object `fun`
.
///
Wraps `fun` into a @ref callback function object
.
/// @relates callback
/// @relates callback
template
<
class
F
>
template
<
class
F
>
auto
make_callback
(
F
fun
)
{
auto
make_callback
(
F
fun
)
{
...
@@ -76,6 +85,24 @@ auto make_callback(F fun) {
...
@@ -76,6 +85,24 @@ auto make_callback(F fun) {
return
callback_impl
<
F
,
signature
>
{
std
::
move
(
fun
)};
return
callback_impl
<
F
,
signature
>
{
std
::
move
(
fun
)};
}
}
}
// namespace caf
/// Creates a heap-allocated, type-erased @ref callback from the function object
/// `fun`.
/// @relates callback
template
<
class
F
>
auto
make_type_erased_callback
(
F
fun
)
{
using
signature
=
typename
detail
::
get_callable_trait
<
F
>::
fun_sig
;
using
result_t
=
unique_callback_ptr
<
signature
>
;
return
result_t
{
new
callback_impl
<
F
,
signature
>
{
std
::
move
(
fun
)}};
}
/// Creates a heap-allocated, type-erased @ref callback from the function object
/// `fun` with shared ownership.
/// @relates callback
template
<
class
F
>
auto
make_shared_type_erased_callback
(
F
fun
)
{
using
signature
=
typename
detail
::
get_callable_trait
<
F
>::
fun_sig
;
auto
res
=
std
::
make_shared
<
callback_impl
<
F
,
signature
>>
(
std
::
move
(
fun
));
return
shared_callback_ptr
<
signature
>
{
std
::
move
(
res
)};
}
CAF_POP_WARNINGS
}
// namespace caf
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