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
ba12dd6c
Commit
ba12dd6c
authored
Dec 28, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'issue/805'
Close #805.
parents
ec6a8927
8b8f785a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
499 additions
and
45 deletions
+499
-45
libcaf_core/caf/actor_config.hpp
libcaf_core/caf/actor_config.hpp
+16
-7
libcaf_core/caf/actor_factory.hpp
libcaf_core/caf/actor_factory.hpp
+3
-5
libcaf_core/caf/detail/init_fun_factory.hpp
libcaf_core/caf/detail/init_fun_factory.hpp
+51
-14
libcaf_core/caf/detail/unique_function.hpp
libcaf_core/caf/detail/unique_function.hpp
+214
-0
libcaf_core/caf/local_actor.hpp
libcaf_core/caf/local_actor.hpp
+2
-1
libcaf_core/test/dynamic_spawn.cpp
libcaf_core/test/dynamic_spawn.cpp
+22
-6
libcaf_core/test/unique_function.cpp
libcaf_core/test/unique_function.cpp
+178
-0
libcaf_io/caf/io/middleman.hpp
libcaf_io/caf/io/middleman.hpp
+13
-12
No files found.
libcaf_core/caf/actor_config.hpp
View file @
ba12dd6c
...
...
@@ -19,26 +19,36 @@
#pragma once
#include <string>
#include <functional>
#include "caf/
fwd
.hpp"
#include "caf/
abstract_channel
.hpp"
#include "caf/behavior.hpp"
#include "caf/detail/unique_function.hpp"
#include "caf/fwd.hpp"
#include "caf/input_range.hpp"
#include "caf/abstract_channel.hpp"
namespace
caf
{
/// Stores spawn-time flags and groups.
class
actor_config
{
public:
// -- member types -----------------------------------------------------------
using
init_fun_type
=
detail
::
unique_function
<
behavior
(
local_actor
*
)
>
;
// -- constructors, destructors, and assignment operators --------------------
explicit
actor_config
(
execution_unit
*
ptr
=
nullptr
);
// -- member variables -------------------------------------------------------
execution_unit
*
host
;
int
flags
;
input_range
<
const
group
>*
groups
;
std
::
function
<
behavior
(
local_actor
*
)
>
init_fun
;
detail
::
unique_function
<
behavior
(
local_actor
*
)
>
init_fun
;
explicit
actor_config
(
execution_unit
*
ptr
=
nullptr
);
// -- properties -------------------------------------------------------------
inline
actor_config
&
add_flag
(
int
x
)
{
actor_config
&
add_flag
(
int
x
)
{
flags
|=
x
;
return
*
this
;
}
...
...
@@ -48,4 +58,3 @@ public:
std
::
string
to_string
(
const
actor_config
&
x
);
}
// namespace caf
libcaf_core/caf/actor_factory.hpp
View file @
ba12dd6c
...
...
@@ -147,21 +147,19 @@ actor_factory make_actor_factory(F fun) {
message_verifier
<
typename
trait
::
arg_types
>
mv
;
if
(
!
mv
(
msg
,
tk
))
return
{};
cfg
.
init_fun
=
[
=
](
local_actor
*
x
)
->
behavior
{
CAF_ASSERT
(
cfg
.
host
);
cfg
.
init_fun
=
actor_config
::
init_fun_type
{[
=
](
local_actor
*
x
)
->
behavior
{
using
ctrait
=
typename
detail
::
get_callable_trait
<
F
>::
type
;
using
fd
=
fun_decorator
<
F
,
impl
,
behavior_t
,
trait
::
mode
,
typename
ctrait
::
result_type
,
typename
ctrait
::
arg_types
>
;
fd
f
{
fun
,
static_cast
<
impl
*>
(
x
)};
empty_type_erased_tuple
dummy_
;
auto
&
ct
=
msg
.
empty
()
?
dummy_
:
const_cast
<
message
&>
(
msg
).
content
();
auto
&
ct
=
msg
.
empty
()
?
dummy_
:
const_cast
<
message
&>
(
msg
).
content
();
auto
opt
=
ct
.
apply
(
f
);
if
(
!
opt
)
return
{};
return
std
::
move
(
*
opt
);
};
}
}
;
handle
hdl
=
cfg
.
host
->
system
().
spawn_class
<
impl
,
no_spawn_options
>
(
cfg
);
return
{
actor_cast
<
strong_actor_ptr
>
(
std
::
move
(
hdl
)),
cfg
.
host
->
system
().
message_types
<
handle
>
()};
...
...
libcaf_core/caf/detail/init_fun_factory.hpp
View file @
ba12dd6c
...
...
@@ -19,36 +19,66 @@
#pragma once
#include <tuple>
#include <functional>
#include "caf/fwd.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/spawn_fwd.hpp"
#include "caf/detail/
type_traits
.hpp"
#include "caf/detail/
unique_function
.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
Base
,
class
F
,
class
ArgsPtr
,
bool
ReturnsBehavior
,
bool
HasSelfPtr
>
class
init_fun_factory_helper
{
class
init_fun_factory_helper_base
:
public
unique_function
<
behavior
(
local_actor
*
)
>::
wrapper
{
public:
init_fun_factory_helper
(
init_fun_factory_helper
&&
)
=
default
;
init_fun_factory_helper
(
const
init_fun_factory_helper
&
)
=
default
;
// -- member types -----------------------------------------------------------
using
super
=
unique_function
<
behavior
(
local_actor
*
)
>::
wrapper
;
using
hook_fun_type
=
unique_function
<
void
(
local_actor
*
)
>
;
// -- constructors, destructors, and assignment operators --------------------
using
super
::
super
;
// -- properties -------------------------------------------------------------
template
<
class
T
>
void
hook
(
T
&&
x
)
{
hook_
=
hook_fun_type
{
std
::
forward
<
T
>
(
x
)};
}
protected:
// -- member variables -------------------------------------------------------
hook_fun_type
hook_
;
};
/// Wraps a user-defined function and gives it a uniform signature.
template
<
class
Base
,
class
F
,
class
ArgsPtr
,
bool
ReturnsBehavior
,
bool
HasSelfPtr
>
class
init_fun_factory_helper
final
:
public
init_fun_factory_helper_base
{
public:
init_fun_factory_helper
(
F
fun
,
ArgsPtr
args
)
:
fun_
(
std
::
move
(
fun
)),
args_
(
std
::
move
(
args
))
{
// nop
}
behavior
operator
()(
local_actor
*
self
)
{
init_fun_factory_helper
(
init_fun_factory_helper
&&
)
=
default
;
init_fun_factory_helper
&
operator
=
(
init_fun_factory_helper
&&
)
=
default
;
behavior
operator
()(
local_actor
*
self
)
final
{
if
(
hook_
!=
nullptr
)
hook_
(
self
);
bool_token
<
ReturnsBehavior
>
returns_behavior_token
;
bool_token
<
HasSelfPtr
>
captures_self_token
;
return
apply
(
returns_behavior_token
,
captures_self_token
,
self
);
}
private:
// behavior (pointer)
behavior
apply
(
std
::
true_type
,
std
::
true_type
,
local_actor
*
ptr
)
{
...
...
@@ -83,10 +113,12 @@ private:
template
<
class
Base
,
class
F
>
class
init_fun_factory
{
public:
using
fun
=
std
::
function
<
behavior
(
local_actor
*
)
>
;
using
ptr_type
=
std
::
unique_ptr
<
init_fun_factory_helper_base
>
;
using
fun
=
unique_function
<
behavior
(
local_actor
*
)
>
;
template
<
class
...
Ts
>
fun
operator
()
(
F
f
,
Ts
&&
...
xs
)
{
ptr_type
make
(
F
f
,
Ts
&&
...
xs
)
{
static_assert
(
std
::
is_base_of
<
local_actor
,
Base
>::
value
,
"Given Base does not extend local_actor"
);
using
trait
=
typename
detail
::
get_callable_trait
<
F
>::
type
;
...
...
@@ -98,10 +130,15 @@ public:
using
tuple_type
=
decltype
(
std
::
make_tuple
(
detail
::
spawn_fwd
<
Ts
>
(
xs
)...));
using
tuple_ptr
=
std
::
shared_ptr
<
tuple_type
>
;
using
helper
=
init_fun_factory_helper
<
Base
,
F
,
tuple_ptr
,
rets
,
selfptr
>
;
return
helper
{
std
::
move
(
f
),
sizeof
...(
Ts
)
>
0
?
std
::
make_shared
<
tuple_type
>
(
detail
::
spawn_fwd
<
Ts
>
(
xs
)...)
:
nullptr
};
return
ptr_type
{
new
helper
{
std
::
move
(
f
),
sizeof
...(
Ts
)
>
0
?
std
::
make_shared
<
tuple_type
>
(
detail
::
spawn_fwd
<
Ts
>
(
xs
)...)
:
nullptr
}};
}
template
<
class
...
Ts
>
fun
operator
()(
F
f
,
Ts
&&
...
xs
)
{
return
fun
{
make
(
std
::
move
(
f
),
std
::
forward
<
Ts
>
(
xs
)...).
release
()};
}
};
...
...
libcaf_core/caf/detail/unique_function.hpp
0 → 100644
View file @
ba12dd6c
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <type_traits>
#include <utility>
namespace
caf
{
namespace
detail
{
/// A move-only replacement for `std::function`.
template
<
class
Signature
>
class
unique_function
;
template
<
class
R
,
class
...
Ts
>
class
unique_function
<
R
(
Ts
...)
>
{
public:
// -- member types -----------------------------------------------------------
/// Function object that dispatches application with a virtual member
/// function.
class
wrapper
{
public:
virtual
~
wrapper
()
{
// nop
}
virtual
R
operator
()(
Ts
...)
=
0
;
};
/// Native function pointer.
using
raw_pointer
=
R
(
*
)(
Ts
...);
/// Pointer to a function wrapper.
using
wrapper_pointer
=
wrapper
*
;
// -- factory functions ------------------------------------------------------
/// Creates a new function object wrapper.
template
<
class
F
>
static
wrapper_pointer
make_wrapper
(
F
&&
f
)
{
class
impl
final
:
public
wrapper
{
public:
impl
(
F
&&
fun
)
:
fun_
(
std
::
move
(
fun
))
{
// nop
}
R
operator
()(
Ts
...
xs
)
override
{
return
fun_
(
xs
...);
}
private:
F
fun_
;
};
return
new
impl
(
std
::
forward
<
F
>
(
f
));
}
// -- constructors, destructors, and assignment operators --------------------
unique_function
()
:
holds_wrapper_
(
false
),
fptr_
(
nullptr
)
{
// nop
}
unique_function
(
unique_function
&&
other
)
:
holds_wrapper_
(
other
.
holds_wrapper_
)
{
fptr_
=
other
.
fptr_
;
if
(
other
.
holds_wrapper_
)
other
.
holds_wrapper_
=
false
;
other
.
fptr_
=
nullptr
;
}
unique_function
(
const
unique_function
&
)
=
delete
;
explicit
unique_function
(
raw_pointer
fun
)
:
holds_wrapper_
(
false
),
fptr_
(
fun
)
{
// nop
}
explicit
unique_function
(
wrapper_pointer
ptr
)
:
holds_wrapper_
(
true
),
wptr_
(
ptr
)
{
// nop
}
template
<
class
T
,
class
=
typename
std
::
enable_if
<
!
std
::
is_convertible
<
T
,
raw_pointer
>
::
value
&&
std
::
is_same
<
decltype
((
std
::
declval
<
T
&>
())(
std
::
declval
<
Ts
>
()...)),
R
>::
value
>::
type
>
explicit
unique_function
(
T
f
)
:
unique_function
(
make_wrapper
(
std
::
move
(
f
)))
{
// nop
}
~
unique_function
()
{
destroy
();
}
// -- assignment -------------------------------------------------------------
unique_function
&
operator
=
(
unique_function
&&
other
)
{
destroy
();
if
(
other
.
holds_wrapper_
)
{
holds_wrapper_
=
true
;
wptr_
=
other
.
wptr_
;
other
.
holds_wrapper_
=
false
;
other
.
fptr_
=
nullptr
;
}
else
{
holds_wrapper_
=
false
;
fptr_
=
other
.
fptr_
;
}
return
*
this
;
}
unique_function
&
operator
=
(
raw_pointer
f
)
{
return
*
this
=
unique_function
{
f
};
}
unique_function
&
operator
=
(
const
unique_function
&
)
=
delete
;
void
assign
(
raw_pointer
f
)
{
*
this
=
unique_function
{
f
};
}
void
assign
(
wrapper_pointer
ptr
)
{
*
this
=
unique_function
{
ptr
};
}
// -- properties -------------------------------------------------------------
bool
is_nullptr
()
const
noexcept
{
// No type dispatching needed, because the union puts both pointers into
// the same memory location.
return
fptr_
==
nullptr
;
}
bool
holds_wrapper
()
const
noexcept
{
return
holds_wrapper_
;
}
// -- operators --------------------------------------------------------------
R
operator
()(
Ts
...
xs
)
{
if
(
holds_wrapper_
)
return
(
*
wptr_
)(
std
::
move
(
xs
)...);
return
(
*
fptr_
)(
std
::
move
(
xs
)...);
}
explicit
operator
bool
()
const
noexcept
{
// No type dispatching needed, because the union puts both pointers into
// the same memory location.
return
!
is_nullptr
();
}
bool
operator
!
()
const
noexcept
{
return
is_nullptr
();
}
private:
// -- destruction ------------------------------------------------------------
/// Destroys the managed wrapper.
void
destroy
()
{
if
(
holds_wrapper_
)
delete
wptr_
;
}
// -- member variables -------------------------------------------------------
bool
holds_wrapper_
;
union
{
raw_pointer
fptr_
;
wrapper_pointer
wptr_
;
};
};
template
<
class
T
>
bool
operator
==
(
const
unique_function
<
T
>&
x
,
std
::
nullptr_t
)
noexcept
{
return
x
.
is_nullptr
();
}
template
<
class
T
>
bool
operator
==
(
std
::
nullptr_t
,
const
unique_function
<
T
>&
x
)
noexcept
{
return
x
.
is_nullptr
();
}
template
<
class
T
>
bool
operator
!=
(
const
unique_function
<
T
>&
x
,
std
::
nullptr_t
)
noexcept
{
return
!
x
.
is_nullptr
();
}
template
<
class
T
>
bool
operator
!=
(
std
::
nullptr_t
,
const
unique_function
<
T
>&
x
)
noexcept
{
return
!
x
.
is_nullptr
();
}
}
// namespace detail
}
// namespace caf
libcaf_core/caf/local_actor.hpp
View file @
ba12dd6c
...
...
@@ -36,6 +36,7 @@
#include "caf/delegated.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/typed_actor_util.hpp"
#include "caf/detail/unique_function.hpp"
#include "caf/duration.hpp"
#include "caf/error.hpp"
#include "caf/fwd.hpp"
...
...
@@ -426,7 +427,7 @@ protected:
message_id
last_request_id_
;
/// Factory function for returning initial behavior in function-based actors.
std
::
function
<
behavior
(
local_actor
*
)
>
initial_behavior_fac_
;
detail
::
unique_function
<
behavior
(
local_actor
*
)
>
initial_behavior_fac_
;
};
}
// namespace caf
...
...
libcaf_core/test/dynamic_spawn.cpp
View file @
ba12dd6c
...
...
@@ -101,14 +101,14 @@ public:
// quits after 5 timeouts
actor
spawn_event_testee2
(
scoped_actor
&
parent
)
{
struct
impl
:
event_based_actor
{
struct
wrapper
:
event_based_actor
{
actor
parent
;
impl
(
actor_config
&
cfg
,
actor
parent_actor
)
wrapper
(
actor_config
&
cfg
,
actor
parent_actor
)
:
event_based_actor
(
cfg
),
parent
(
std
::
move
(
parent_actor
))
{
inc_actor_instances
();
}
~
impl
()
override
{
~
wrapper
()
override
{
dec_actor_instances
();
}
behavior
wait4timeout
(
int
remaining
)
{
...
...
@@ -127,7 +127,7 @@ actor spawn_event_testee2(scoped_actor& parent) {
return
wait4timeout
(
5
);
}
};
return
parent
->
spawn
<
impl
>
(
parent
);
return
parent
->
spawn
<
wrapper
>
(
parent
);
}
class
testee_actor
:
public
blocking_actor
{
...
...
@@ -555,7 +555,7 @@ CAF_TEST(kill_the_immortal) {
CAF_TEST
(
move_only_argument
)
{
using
unique_int
=
std
::
unique_ptr
<
int
>
;
unique_int
uptr
{
new
int
(
42
)};
auto
impl
=
[](
event_based_actor
*
self
,
unique_int
ptr
)
->
behavior
{
auto
wrapper
=
[](
event_based_actor
*
self
,
unique_int
ptr
)
->
behavior
{
auto
i
=
*
ptr
;
return
{
[
=
](
float
)
{
...
...
@@ -564,8 +564,24 @@ CAF_TEST(move_only_argument) {
}
};
};
auto
f
=
make_function_view
(
system
.
spawn
(
impl
,
std
::
move
(
uptr
)));
auto
f
=
make_function_view
(
system
.
spawn
(
wrapper
,
std
::
move
(
uptr
)));
CAF_CHECK_EQUAL
(
to_string
(
f
(
1.
f
)),
"(42)"
);
}
CAF_TEST
(
move
-
only
function
object
)
{
struct
move_only_fun
{
move_only_fun
()
=
default
;
move_only_fun
(
const
move_only_fun
&
)
=
delete
;
move_only_fun
(
move_only_fun
&&
)
=
default
;
behavior
operator
()(
event_based_actor
*
)
{
return
{};
}
};
actor_system_config
cfg
;
actor_system
sys
{
cfg
};
move_only_fun
f
;
sys
.
spawn
(
std
::
move
(
f
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/unique_function.cpp
0 → 100644
View file @
ba12dd6c
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE unique_function
#include "caf/detail/unique_function.hpp"
#include "caf/test/dsl.hpp"
namespace
{
using
int_fun
=
caf
::
detail
::
unique_function
<
int
()
>
;
int
fourty_two
()
{
return
42
;
}
class
instance_counting_wrapper
final
:
public
int_fun
::
wrapper
{
public:
instance_counting_wrapper
(
size_t
*
instance_counter
)
:
instance_counter_
(
instance_counter
)
{
*
instance_counter_
+=
1
;
}
~
instance_counting_wrapper
()
{
*
instance_counter_
-=
1
;
}
int
operator
()()
final
{
return
42
;
}
private:
size_t
*
instance_counter_
;
};
}
// namespace <anonymous>
#define CHECK_VALID(f) \
CAF_CHECK(!f.is_nullptr()); \
CAF_CHECK(f); \
CAF_CHECK(f != nullptr); \
CAF_CHECK(nullptr != f); \
CAF_CHECK(!(f == nullptr)); \
CAF_CHECK(!(nullptr == f)); \
CAF_CHECK(f() == 42)
#define CHECK_INVALID(f) \
CAF_CHECK(f.is_nullptr()); \
CAF_CHECK(!f); \
CAF_CHECK(f == nullptr); \
CAF_CHECK(nullptr == f); \
CAF_CHECK(!(f != nullptr)); \
CAF_CHECK(!(nullptr != f)); \
CAF_CHECK(!f.holds_wrapper())
CAF_TEST
(
default
construction
)
{
int_fun
f
;
CHECK_INVALID
(
f
);
}
CAF_TEST
(
raw
function
pointer
construction
)
{
int_fun
f
{
fourty_two
};
CHECK_VALID
(
f
);
}
CAF_TEST
(
stateless
lambda
construction
)
{
int_fun
f
{[]
{
return
42
;
}};
CHECK_VALID
(
f
);
CAF_CHECK
(
!
f
.
holds_wrapper
());
}
CAF_TEST
(
stateful
lambda
construction
)
{
int
i
=
42
;
int_fun
f
{[
=
]
{
return
i
;
}};
CHECK_VALID
(
f
);
CAF_CHECK
(
f
.
holds_wrapper
());
}
CAF_TEST
(
custom
wrapper
construction
)
{
size_t
instances
=
0
;
{
// lifetime scope of our counting wrapper
int_fun
f
{
new
instance_counting_wrapper
(
&
instances
)};
CHECK_VALID
(
f
);
CAF_CHECK
(
f
.
holds_wrapper
());
CAF_CHECK
(
instances
==
1
);
}
CAF_CHECK
(
instances
==
0
);
}
CAF_TEST
(
function
move
construction
)
{
int_fun
f
{
fourty_two
};
int_fun
g
{
std
::
move
(
f
)};
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CAF_CHECK
(
!
g
.
holds_wrapper
());
}
CAF_TEST
(
stateful
lambda
move
construction
)
{
int
i
=
42
;
int_fun
f
{[
=
]
{
return
i
;
}};
int_fun
g
{
std
::
move
(
f
)};
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CAF_CHECK
(
g
.
holds_wrapper
());
}
CAF_TEST
(
custom
wrapper
move
construction
)
{
size_t
instances
=
0
;
{
// lifetime scope of our counting wrapper
int_fun
f
{
new
instance_counting_wrapper
(
&
instances
)};
int_fun
g
{
std
::
move
(
f
)};
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CAF_CHECK
(
g
.
holds_wrapper
());
CAF_CHECK
(
instances
==
1
);
}
CAF_CHECK
(
instances
==
0
);
}
CAF_TEST
(
function
assign
)
{
size_t
instances
=
0
;
int_fun
f
;
int_fun
g
{
fourty_two
};
int_fun
h
{
new
instance_counting_wrapper
(
&
instances
)};
CAF_CHECK
(
instances
==
1
);
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CHECK_VALID
(
h
);
f
=
fourty_two
;
g
=
fourty_two
;
h
=
fourty_two
;
CAF_CHECK
(
instances
==
0
);
CHECK_VALID
(
f
);
CHECK_VALID
(
g
);
CHECK_VALID
(
h
);
}
CAF_TEST
(
move
assign
)
{
size_t
instances
=
0
;
int_fun
f
;
int_fun
g
{
fourty_two
};
int_fun
h
{
new
instance_counting_wrapper
(
&
instances
)};
CAF_CHECK
(
instances
==
1
);
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CHECK_VALID
(
h
);
g
=
std
::
move
(
h
);
CAF_CHECK
(
instances
==
1
);
CHECK_INVALID
(
f
);
CHECK_VALID
(
g
);
CHECK_INVALID
(
h
);
f
=
std
::
move
(
g
);
CAF_CHECK
(
instances
==
1
);
CHECK_VALID
(
f
);
CHECK_INVALID
(
g
);
CHECK_INVALID
(
h
);
f
=
int_fun
{};
CAF_CHECK
(
instances
==
0
);
CHECK_INVALID
(
f
);
CHECK_INVALID
(
g
);
CHECK_INVALID
(
h
);
}
libcaf_io/caf/io/middleman.hpp
View file @
ba12dd6c
...
...
@@ -23,12 +23,13 @@
#include <memory>
#include <thread>
#include "caf/actor_system.hpp"
#include "caf/detail/unique_function.hpp"
#include "caf/expected.hpp"
#include "caf/fwd.hpp"
#include "caf/send.hpp"
#include "caf/node_id.hpp"
#include "caf/expected.hpp"
#include "caf/actor_system.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/send.hpp"
#include "caf/io/hook.hpp"
#include "caf/io/broker.hpp"
...
...
@@ -336,11 +337,11 @@ private:
CAF_ASSERT
(
ptr
!=
nullptr
);
detail
::
init_fun_factory
<
Impl
,
F
>
fac
;
actor_config
cfg
{
&
backend
()};
auto
init_fun
=
fac
(
std
::
move
(
fun
),
ptr
->
hdl
(),
std
::
forward
<
Ts
>
(
xs
)...);
cfg
.
init_fun
=
[
ptr
,
init_fun
](
local_actor
*
self
)
mutable
->
behavior
{
auto
fptr
=
fac
.
make
(
std
::
move
(
fun
),
ptr
->
hdl
(),
std
::
forward
<
Ts
>
(
xs
)...);
fptr
->
hook
([
=
](
local_actor
*
self
)
mutable
{
static_cast
<
abstract_broker
*>
(
self
)
->
add_scribe
(
std
::
move
(
ptr
));
return
init_fun
(
self
);
}
;
}
);
cfg
.
init_fun
.
assign
(
fptr
.
release
())
;
return
system
().
spawn_class
<
Impl
,
Os
>
(
cfg
);
}
...
...
@@ -352,13 +353,13 @@ private:
return
eptr
.
error
();
auto
ptr
=
std
::
move
(
*
eptr
);
detail
::
init_fun_factory
<
Impl
,
F
>
fac
;
auto
init_fun
=
fac
(
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
xs
)...);
port
=
ptr
->
port
();
a
ctor_config
cfg
{
&
backend
()}
;
cfg
.
init_fun
=
[
ptr
,
init_fun
](
local_actor
*
self
)
mutable
->
behavior
{
a
uto
fptr
=
fac
.
make
(
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
xs
)...)
;
fptr
->
hook
([
=
](
local_actor
*
self
)
mutable
{
static_cast
<
abstract_broker
*>
(
self
)
->
add_doorman
(
std
::
move
(
ptr
));
return
init_fun
(
self
);
};
});
actor_config
cfg
{
&
backend
()};
cfg
.
init_fun
.
assign
(
fptr
.
release
());
return
system
().
spawn_class
<
Impl
,
Os
>
(
cfg
);
}
...
...
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