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
94f186a5
Commit
94f186a5
authored
Jun 24, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor blocking actors to not use exceptions
parent
e4855afe
Changes
65
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
65 changed files
with
1730 additions
and
916 deletions
+1730
-916
examples/dynamic_behavior/skip_messages.cpp
examples/dynamic_behavior/skip_messages.cpp
+14
-5
examples/message_passing/calculator.cpp
examples/message_passing/calculator.cpp
+16
-7
examples/message_passing/request.cpp
examples/message_passing/request.cpp
+9
-3
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+4
-1
libcaf_core/caf/actor_companion.hpp
libcaf_core/caf/actor_companion.hpp
+0
-2
libcaf_core/caf/all.hpp
libcaf_core/caf/all.hpp
+0
-1
libcaf_core/caf/blocking_actor.hpp
libcaf_core/caf/blocking_actor.hpp
+159
-61
libcaf_core/caf/catch_all.hpp
libcaf_core/caf/catch_all.hpp
+58
-0
libcaf_core/caf/detail/behavior_impl.hpp
libcaf_core/caf/detail/behavior_impl.hpp
+28
-6
libcaf_core/caf/detail/blocking_behavior.hpp
libcaf_core/caf/detail/blocking_behavior.hpp
+144
-0
libcaf_core/caf/detail/default_invoke_result_visitor.hpp
libcaf_core/caf/detail/default_invoke_result_visitor.hpp
+92
-0
libcaf_core/caf/detail/private_thread.hpp
libcaf_core/caf/detail/private_thread.hpp
+69
-0
libcaf_core/caf/event_based_actor.hpp
libcaf_core/caf/event_based_actor.hpp
+4
-2
libcaf_core/caf/expected.hpp
libcaf_core/caf/expected.hpp
+22
-0
libcaf_core/caf/function_view.hpp
libcaf_core/caf/function_view.hpp
+34
-9
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+2
-0
libcaf_core/caf/is_timeout_or_catch_all.hpp
libcaf_core/caf/is_timeout_or_catch_all.hpp
+39
-0
libcaf_core/caf/local_actor.hpp
libcaf_core/caf/local_actor.hpp
+17
-83
libcaf_core/caf/match_case.hpp
libcaf_core/caf/match_case.hpp
+2
-0
libcaf_core/caf/others.hpp
libcaf_core/caf/others.hpp
+45
-0
libcaf_core/caf/response_handle.hpp
libcaf_core/caf/response_handle.hpp
+18
-27
libcaf_core/caf/scheduled_actor.hpp
libcaf_core/caf/scheduled_actor.hpp
+136
-0
libcaf_core/caf/sec.hpp
libcaf_core/caf/sec.hpp
+3
-1
libcaf_core/caf/typed_actor_view.hpp
libcaf_core/caf/typed_actor_view.hpp
+3
-3
libcaf_core/caf/typed_event_based_actor.hpp
libcaf_core/caf/typed_event_based_actor.hpp
+4
-2
libcaf_core/src/abstract_coordinator.cpp
libcaf_core/src/abstract_coordinator.cpp
+14
-14
libcaf_core/src/actor_companion.cpp
libcaf_core/src/actor_companion.cpp
+0
-4
libcaf_core/src/actor_registry.cpp
libcaf_core/src/actor_registry.cpp
+0
-1
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+4
-2
libcaf_core/src/blocking_actor.cpp
libcaf_core/src/blocking_actor.cpp
+136
-30
libcaf_core/src/blocking_behavior.cpp
libcaf_core/src/blocking_behavior.cpp
+10
-54
libcaf_core/src/default_invoke_result_visitor.cpp
libcaf_core/src/default_invoke_result_visitor.cpp
+30
-0
libcaf_core/src/local_actor.cpp
libcaf_core/src/local_actor.cpp
+36
-420
libcaf_core/src/private_thread.cpp
libcaf_core/src/private_thread.cpp
+114
-0
libcaf_core/src/scheduled_actor.cpp
libcaf_core/src/scheduled_actor.cpp
+222
-0
libcaf_core/src/sec.cpp
libcaf_core/src/sec.cpp
+3
-2
libcaf_core/test/actor_factory.cpp
libcaf_core/test/actor_factory.cpp
+1
-0
libcaf_core/test/actor_pool.cpp
libcaf_core/test/actor_pool.cpp
+16
-6
libcaf_core/test/actor_termination.cpp
libcaf_core/test/actor_termination.cpp
+2
-4
libcaf_core/test/adapter.cpp
libcaf_core/test/adapter.cpp
+18
-7
libcaf_core/test/atom.cpp
libcaf_core/test/atom.cpp
+5
-1
libcaf_core/test/composable_behavior.cpp
libcaf_core/test/composable_behavior.cpp
+19
-7
libcaf_core/test/custom_exception_handler.cpp
libcaf_core/test/custom_exception_handler.cpp
+0
-14
libcaf_core/test/dynamic_spawn.cpp
libcaf_core/test/dynamic_spawn.cpp
+28
-31
libcaf_core/test/function_view.cpp
libcaf_core/test/function_view.cpp
+2
-14
libcaf_core/test/or_else.cpp
libcaf_core/test/or_else.cpp
+21
-9
libcaf_core/test/parse_ini.cpp
libcaf_core/test/parse_ini.cpp
+9
-3
libcaf_core/test/request_response.cpp
libcaf_core/test/request_response.cpp
+17
-14
libcaf_core/test/sequencer.cpp
libcaf_core/test/sequencer.cpp
+6
-4
libcaf_core/test/splitter.cpp
libcaf_core/test/splitter.cpp
+7
-2
libcaf_core/test/stateful_actor.cpp
libcaf_core/test/stateful_actor.cpp
+7
-2
libcaf_core/test/typed_response_promise.cpp
libcaf_core/test/typed_response_promise.cpp
+13
-7
libcaf_core/test/typed_spawn.cpp
libcaf_core/test/typed_spawn.cpp
+11
-4
libcaf_io/caf/io/abstract_broker.hpp
libcaf_io/caf/io/abstract_broker.hpp
+32
-18
libcaf_io/caf/io/network/asio_multiplexer_impl.hpp
libcaf_io/caf/io/network/asio_multiplexer_impl.hpp
+0
-2
libcaf_io/caf/io/network/default_multiplexer.hpp
libcaf_io/caf/io/network/default_multiplexer.hpp
+0
-1
libcaf_io/src/abstract_broker.cpp
libcaf_io/src/abstract_broker.cpp
+3
-3
libcaf_io/src/basp_broker.cpp
libcaf_io/src/basp_broker.cpp
+0
-1
libcaf_io/src/default_multiplexer.cpp
libcaf_io/src/default_multiplexer.cpp
+2
-1
libcaf_io/src/middleman.cpp
libcaf_io/src/middleman.cpp
+6
-7
libcaf_io/src/middleman_actor.cpp
libcaf_io/src/middleman_actor.cpp
+0
-1
libcaf_io/test/basp.cpp
libcaf_io/test/basp.cpp
+3
-0
libcaf_io/test/remote_group.cpp
libcaf_io/test/remote_group.cpp
+3
-0
libcaf_io/test/typed_broker.cpp
libcaf_io/test/typed_broker.cpp
+3
-0
libcaf_io/test/typed_remote_actor.cpp
libcaf_io/test/typed_remote_actor.cpp
+5
-13
No files found.
examples/dynamic_behavior/skip_messages.cpp
View file @
94f186a5
...
...
@@ -40,11 +40,20 @@ void caf_main(actor_system& system) {
auto
serv
=
system
.
spawn
(
server
);
auto
worker
=
system
.
spawn
(
client
,
serv
);
scoped_actor
self
{
system
};
self
->
request
(
serv
,
std
::
chrono
::
seconds
(
10
),
request_atom
::
value
).
receive
([
&
](
response_atom
)
{
aout
(
self
)
<<
"received response from "
<<
(
self
->
current_sender
()
==
worker
?
"worker
\n
"
:
"server
\n
"
);
});
self
->
request
(
serv
,
std
::
chrono
::
seconds
(
10
),
request_atom
::
value
).
receive
(
[
&
](
response_atom
)
{
aout
(
self
)
<<
"received response from "
<<
(
self
->
current_sender
()
==
worker
?
"worker
\n
"
:
"server
\n
"
);
},
[
&
](
error
&
err
)
{
aout
(
self
)
<<
"received error "
<<
system
.
render
(
err
)
<<
" from "
<<
(
self
->
current_sender
()
==
worker
?
"worker
\n
"
:
"server
\n
"
);
}
);
self
->
send_exit
(
serv
,
exit_reason
::
user_shutdown
);
}
...
...
examples/message_passing/calculator.cpp
View file @
94f186a5
...
...
@@ -42,12 +42,19 @@ behavior calculator_fun(event_based_actor*) {
// function-based, dynamically typed, blocking API
void
blocking_calculator_fun
(
blocking_actor
*
self
)
{
self
->
receive_loop
(
bool
running
=
true
;
self
->
receive_while
(
running
)
(
[](
add_atom
,
int
a
,
int
b
)
{
return
a
+
b
;
},
[](
sub_atom
,
int
a
,
int
b
)
{
return
a
-
b
;
},
[
&
](
exit_msg
&
em
)
{
if
(
em
.
reason
)
{
self
->
fail_state
(
std
::
move
(
em
.
reason
));
running
=
false
;
}
}
);
}
...
...
@@ -107,6 +114,11 @@ void tester(scoped_actor&) {
// tests a calculator instance
template
<
class
Handle
,
class
...
Ts
>
void
tester
(
scoped_actor
&
self
,
const
Handle
&
hdl
,
int
x
,
int
y
,
Ts
&&
...
xs
)
{
auto
handle_err
=
[
&
](
const
error
&
err
)
{
aout
(
self
)
<<
"AUT (actor under test) failed: "
<<
self
->
system
().
render
(
err
)
<<
endl
;
throw
std
::
runtime_error
(
"AUT responded with an error"
);
};
// first test: x + y = z
self
->
request
(
hdl
,
infinite
,
add_atom
::
value
,
x
,
y
).
receive
(
[
&
](
int
res1
)
{
...
...
@@ -115,14 +127,11 @@ void tester(scoped_actor& self, const Handle& hdl, int x, int y, Ts&&... xs) {
self
->
request
(
hdl
,
infinite
,
sub_atom
::
value
,
x
,
y
).
receive
(
[
&
](
int
res2
)
{
aout
(
self
)
<<
x
<<
" - "
<<
y
<<
" = "
<<
res2
<<
endl
;
}
},
handle_err
);
},
[
&
](
const
error
&
err
)
{
aout
(
self
)
<<
"AUT (actor under test) failed: "
<<
self
->
system
().
render
(
err
)
<<
endl
;
self
->
quit
(
exit_reason
::
user_shutdown
);
}
handle_err
);
tester
(
self
,
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
examples/message_passing/request.cpp
View file @
94f186a5
...
...
@@ -52,9 +52,15 @@ void multiplexed_testee(event_based_actor* self, vector<cell> cells) {
void
blocking_testee
(
blocking_actor
*
self
,
vector
<
cell
>
cells
)
{
for
(
auto
&
x
:
cells
)
self
->
request
(
x
,
seconds
(
1
),
get_atom
::
value
).
receive
([
&
](
int
y
)
{
aout
(
self
)
<<
"cell #"
<<
x
.
id
()
<<
" -> "
<<
y
<<
endl
;
});
self
->
request
(
x
,
seconds
(
1
),
get_atom
::
value
).
receive
(
[
&
](
int
y
)
{
aout
(
self
)
<<
"cell #"
<<
x
.
id
()
<<
" -> "
<<
y
<<
endl
;
},
[
&
](
error
&
err
)
{
aout
(
self
)
<<
"cell #"
<<
x
.
id
()
<<
" -> "
<<
self
->
system
().
render
(
err
)
<<
endl
;
}
);
}
void
caf_main
(
actor_system
&
system
)
{
...
...
libcaf_core/CMakeLists.txt
View file @
94f186a5
...
...
@@ -34,10 +34,12 @@ set (LIBCAF_CORE_SRCS
src/behavior_stack.cpp
src/behavior_impl.cpp
src/blocking_actor.cpp
src/blocking_behavior.cpp
src/concatenated_tuple.cpp
src/config_option.cpp
src/continue_helper.cpp
src/decorated_tuple.cpp
src/default_invoke_result_visitor.cpp
src/deep_to_string.cpp
src/default_attachable.cpp
src/deserializer.cpp
...
...
@@ -45,7 +47,6 @@ set (LIBCAF_CORE_SRCS
src/dynamic_message_data.cpp
src/error.cpp
src/event_based_actor.cpp
src/exception.cpp
src/execution_unit.cpp
src/exit_reason.cpp
src/forwarding_actor_proxy.cpp
...
...
@@ -69,12 +70,14 @@ set (LIBCAF_CORE_SRCS
src/message_handler.cpp
src/node_id.cpp
src/parse_ini.cpp
src/private_thread.cpp
src/ref_counted.cpp
src/proxy_registry.cpp
src/response_promise.cpp
src/replies_to.cpp
src/resumable.cpp
src/ripemd_160.cpp
src/scheduled_actor.cpp
src/scoped_actor.cpp
src/scoped_execution_unit.cpp
src/sec.cpp
...
...
libcaf_core/caf/actor_companion.hpp
View file @
94f186a5
...
...
@@ -59,8 +59,6 @@ public:
void
enqueue
(
strong_actor_ptr
sender
,
message_id
mid
,
message
content
,
execution_unit
*
host
)
override
;
void
initialize
()
override
;
private:
// set by parent to define custom enqueue action
enqueue_handler
on_enqueue_
;
...
...
libcaf_core/caf/all.hpp
View file @
94f186a5
...
...
@@ -39,7 +39,6 @@
#include "caf/behavior.hpp"
#include "caf/duration.hpp"
#include "caf/expected.hpp"
#include "caf/exception.hpp"
#include "caf/exec_main.hpp"
#include "caf/resumable.hpp"
#include "caf/streambuf.hpp"
...
...
libcaf_core/caf/blocking_actor.hpp
View file @
94f186a5
This diff is collapsed.
Click to expand it.
libcaf_core/caf/catch_all.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_CATCH_ALL_HPP
#define CAF_CATCH_ALL_HPP
#include <functional>
#include <type_traits>
namespace
caf
{
template
<
class
F
>
struct
catch_all
{
using
fun_type
=
std
::
function
<
result
<
message
>
(
const
type_erased_tuple
*
)
>
;
F
handler
;
catch_all
(
catch_all
&&
)
=
default
;
template
<
class
T
>
catch_all
(
T
&&
x
)
:
handler
(
std
::
forward
<
T
>
(
x
))
{
// nop
}
static_assert
(
std
::
is_convertible
<
F
,
fun_type
>::
value
,
"catch-all handler must have signature "
"result<message> (const type_erased_tuple*)"
);
fun_type
lift
()
const
{
return
handler
;
}
};
template
<
class
T
>
struct
is_catch_all
:
std
::
false_type
{};
template
<
class
T
>
struct
is_catch_all
<
catch_all
<
T
>>
:
std
::
true_type
{};
}
// namespace caf
#endif // CAF_CATCH_ALL_HPP
libcaf_core/caf/detail/behavior_impl.hpp
View file @
94f186a5
...
...
@@ -221,15 +221,37 @@ default_behavior_impl<std::tuple<Ts...>>::copy(const generic_timeout_definition&
return
apply_args_suffxied
(
factory
,
indices
,
cases_
,
td
);
}
template
<
class
...
Ts
>
intrusive_ptr
<
default_behavior_impl
<
std
::
tuple
<
typename
lift_behavior
<
Ts
>::
type
...
>>>
make_behavior
(
Ts
...
xs
)
{
using
type
=
default_behavior_impl
<
std
::
tuple
<
typename
lift_behavior
<
Ts
>::
type
...
>>
;
return
make_counted
<
type
>
(
std
::
move
(
xs
)...);
}
struct
make_behavior_t
{
constexpr
make_behavior_t
()
{
// nop
}
template
<
class
...
Ts
>
intrusive_ptr
<
default_behavior_impl
<
std
::
tuple
<
typename
lift_behavior
<
Ts
>::
type
...
>>>
operator
()(
Ts
...
xs
)
const
{
using
type
=
default_behavior_impl
<
std
::
tuple
<
typename
lift_behavior
<
Ts
>::
type
...
>>
;
return
make_counted
<
type
>
(
std
::
move
(
xs
)...);
}
};
constexpr
make_behavior_t
make_behavior
=
make_behavior_t
{};
using
behavior_impl_ptr
=
intrusive_ptr
<
behavior_impl
>
;
// utility for getting a type-erased version of make_behavior
struct
make_behavior_impl_t
{
constexpr
make_behavior_impl_t
()
{
// nop
}
template
<
class
...
Ts
>
behavior_impl_ptr
operator
()(
Ts
&&
...
xs
)
const
{
return
make_behavior
(
std
::
forward
<
Ts
>
(
xs
)...);
}
};
constexpr
make_behavior_impl_t
make_behavior_impl
=
make_behavior_impl_t
{};
}
// namespace detail
}
// namespace caf
...
...
libcaf_core/caf/detail/blocking_behavior.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_BLOCKING_BEHAVIOR_HPP
#define CAF_BLOCKING_BEHAVIOR_HPP
#include "caf/behavior.hpp"
#include "caf/catch_all.hpp"
#include "caf/timeout_definition.hpp"
namespace
caf
{
namespace
detail
{
class
blocking_behavior
{
public:
behavior
nested
;
blocking_behavior
(
behavior
nested
);
blocking_behavior
(
blocking_behavior
&&
)
=
default
;
virtual
~
blocking_behavior
();
virtual
result
<
message
>
fallback
(
const
type_erased_tuple
*
);
virtual
duration
timeout
();
virtual
void
handle_timeout
();
};
template
<
class
F
>
class
blocking_behavior_v2
:
public
blocking_behavior
{
public:
catch_all
<
F
>
f
;
blocking_behavior_v2
(
behavior
x
,
catch_all
<
F
>
y
)
:
blocking_behavior
(
std
::
move
(
x
)),
f
(
std
::
move
(
y
))
{
// nop
}
blocking_behavior_v2
(
blocking_behavior_v2
&&
)
=
default
;
result
<
message
>
fallback
(
const
type_erased_tuple
*
x
)
override
{
return
f
.
handler
(
x
);
}
};
template
<
class
F
>
class
blocking_behavior_v3
:
public
blocking_behavior
{
public:
timeout_definition
<
F
>
f
;
blocking_behavior_v3
(
behavior
x
,
timeout_definition
<
F
>
y
)
:
blocking_behavior
(
std
::
move
(
x
)),
f
(
std
::
move
(
y
))
{
// nop
}
blocking_behavior_v3
(
blocking_behavior_v3
&&
)
=
default
;
duration
timeout
()
override
{
return
f
.
timeout
;
}
void
handle_timeout
()
override
{
f
.
handler
();
}
};
template
<
class
F1
,
class
F2
>
class
blocking_behavior_v4
:
public
blocking_behavior
{
public:
catch_all
<
F1
>
f1
;
timeout_definition
<
F2
>
f2
;
blocking_behavior_v4
(
behavior
x
,
catch_all
<
F1
>
y
,
timeout_definition
<
F2
>
z
)
:
blocking_behavior
(
std
::
move
(
x
)),
f1
(
std
::
move
(
y
)),
f2
(
std
::
move
(
z
))
{
// nop
}
blocking_behavior_v4
(
blocking_behavior_v4
&&
)
=
default
;
result
<
message
>
fallback
(
const
type_erased_tuple
*
x
)
override
{
return
f1
.
handler
(
x
);
}
duration
timeout
()
override
{
return
f2
.
timeout
;
}
void
handle_timeout
()
override
{
f2
.
handler
();
}
};
struct
make_blocking_behavior_t
{
constexpr
make_blocking_behavior_t
()
{
// nop
}
inline
blocking_behavior
operator
()(
behavior
&
x
)
const
{
return
{
std
::
move
(
x
)};
}
template
<
class
F
>
blocking_behavior_v2
<
F
>
operator
()(
behavior
&
x
,
catch_all
<
F
>&
y
)
const
{
return
{
std
::
move
(
x
),
std
::
move
(
y
)};
}
template
<
class
F
>
blocking_behavior_v3
<
F
>
operator
()(
behavior
&
x
,
timeout_definition
<
F
>&
y
)
const
{
return
{
std
::
move
(
x
),
std
::
move
(
y
)};
}
template
<
class
F1
,
class
F2
>
blocking_behavior_v4
<
F1
,
F2
>
operator
()(
behavior
&
x
,
catch_all
<
F1
>&
y
,
timeout_definition
<
F2
>&
z
)
const
{
return
{
std
::
move
(
x
),
std
::
move
(
y
),
std
::
move
(
z
)};
}
};
}
// namespace detail
}
// namespace caf
#endif // CAF_BLOCKING_BEHAVIOR_HPP
libcaf_core/caf/
exception
.hpp
→
libcaf_core/caf/
detail/default_invoke_result_visitor
.hpp
View file @
94f186a5
...
...
@@ -17,77 +17,76 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_
EXCEPTION
_HPP
#define CAF_
EXCEPTION
_HPP
#ifndef CAF_
DETAIL_DEFAULT_INVOKE_VISITOR
_HPP
#define CAF_
DETAIL_DEFAULT_INVOKE_VISITOR
_HPP
#include <string>
#include <cstdint>
#include <exception>
#include <stdexcept>
#include "caf/local_actor.hpp"
#include "caf/
exit_reason
.hpp"
#include "caf/
detail/invoke_result_visitor
.hpp"
namespace
caf
{
namespace
detail
{
/// Base class for exceptions.
class
caf_exception
:
public
std
::
exception
{
class
default_invoke_result_visitor
:
public
invoke_result_visitor
{
public:
~
caf_exception
()
noexcept
;
inline
default_invoke_result_visitor
(
local_actor
*
ptr
)
:
self_
(
ptr
)
{
// nop
}
caf_exception
()
=
delete
;
caf_exception
(
const
caf_exception
&
)
=
default
;
caf_exception
&
operator
=
(
const
caf_exception
&
)
=
default
;
~
default_invoke_result_visitor
();
/// Returns the error message.
const
char
*
what
()
const
noexcept
;
void
operator
()()
override
{
// nop
}
protected:
/// Creates an exception with the error string `what_str`.
explicit
caf_exception
(
std
::
string
what_str
);
void
operator
()(
error
&
x
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
delegate
(
x
);
}
private:
std
::
string
what_
;
};
void
operator
()(
message
&
x
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
delegate
(
x
);
}
/// Thrown if an actor finished execution.
class
actor_exited
:
public
caf_exception
{
public:
~
actor_exited
()
noexcept
;
explicit
actor_exited
(
error
exit_reason
);
actor_exited
(
const
actor_exited
&
)
=
default
;
actor_exited
&
operator
=
(
const
actor_exited
&
)
=
default
;
/// Returns the exit reason.
inline
error
reason
()
const
noexcept
{
return
reason_
;
void
operator
()(
const
none_t
&
x
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
delegate
(
x
);
}
private:
error
reason_
;
};
void
deliver
(
response_promise
&
rp
,
error
&
x
)
{
CAF_LOG_DEBUG
(
"report error back to requesting actor"
);
rp
.
deliver
(
std
::
move
(
x
));
}
/// Thrown to indicate that either an actor publishing failed or
/// the middleman was unable to connect to a remote host.
class
network_error
:
public
caf_exception
{
public:
~
network_error
()
noexcept
;
explicit
network_error
(
std
::
string
&&
what_str
);
explicit
network_error
(
const
std
::
string
&
what_str
);
network_error
(
const
network_error
&
)
=
default
;
network_error
&
operator
=
(
const
network_error
&
)
=
default
;
};
void
deliver
(
response_promise
&
rp
,
message
&
x
)
{
CAF_LOG_DEBUG
(
"respond via response_promise"
);
// suppress empty messages for asynchronous messages
if
(
x
.
empty
()
&&
rp
.
async
())
return
;
rp
.
deliver
(
std
::
move
(
x
));
}
/// Thrown to indicate that an actor publishing failed because
/// the requested port could not be used.
class
bind_failure
:
public
network_error
{
public:
~
bind_failure
()
noexcept
;
explicit
bind_failure
(
std
::
string
&&
what_str
);
explicit
bind_failure
(
const
std
::
string
&
what_str
);
bind_failure
(
const
bind_failure
&
)
=
default
;
bind_failure
&
operator
=
(
const
bind_failure
&
)
=
default
;
void
deliver
(
response_promise
&
rp
,
const
none_t
&
)
{
error
err
=
sec
::
unexpected_response
;
deliver
(
rp
,
err
);
}
template
<
class
T
>
void
delegate
(
T
&
x
)
{
auto
rp
=
self_
->
make_response_promise
();
if
(
!
rp
.
pending
())
{
CAF_LOG_DEBUG
(
"suppress response message: invalid response promise"
);
return
;
}
deliver
(
rp
,
x
);
}
local_actor
*
self_
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_
EXCEPTION
_HPP
#endif // CAF_
DETAIL_DEFAULT_INVOKE_VISITOR
_HPP
libcaf_core/caf/detail/private_thread.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_DETAIL_PRIVATE_THREAD_HPP
#define CAF_DETAIL_PRIVATE_THREAD_HPP
#include <mutex>
#include <condition_variable>
#include "caf/fwd.hpp"
namespace
caf
{
namespace
detail
{
class
private_thread
{
public:
enum
worker_state
{
active
,
shutdown_requested
,
await_resume_or_shutdown
};
private_thread
(
scheduled_actor
*
self
);
void
run
();
bool
await_resume
();
void
resume
();
void
shutdown
();
static
void
exec
(
private_thread
*
this_ptr
);
void
notify_self_destroyed
();
void
await_self_destroyed
();
void
start
();
private:
std
::
mutex
mtx_
;
std
::
condition_variable
cv_
;
volatile
bool
self_destroyed_
;
volatile
scheduled_actor
*
self_
;
volatile
worker_state
state_
;
actor_system
&
system_
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_PRIVATE_THREAD_HPP
libcaf_core/caf/event_based_actor.hpp
View file @
94f186a5
...
...
@@ -27,6 +27,7 @@
#include "caf/local_actor.hpp"
#include "caf/actor_marker.hpp"
#include "caf/response_handle.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/mixin/sender.hpp"
#include "caf/mixin/requester.hpp"
...
...
@@ -45,12 +46,13 @@ public:
/// A cooperatively scheduled, event-based actor implementation. This is the
/// recommended base class for user-defined actors.
/// @extends local_actor
class
event_based_actor
:
public
extend
<
local_actor
,
event_based_actor
>::
class
event_based_actor
:
public
extend
<
scheduled_actor
,
event_based_actor
>::
with
<
mixin
::
sender
,
mixin
::
requester
,
mixin
::
behavior_changer
>
,
public
dynamically_typed_actor_base
{
public:
using
super
=
extend
<
local
_actor
,
event_based_actor
>::
using
super
=
extend
<
scheduled
_actor
,
event_based_actor
>::
with
<
mixin
::
sender
,
mixin
::
requester
,
mixin
::
behavior_changer
>
;
using
signatures
=
none_t
;
...
...
libcaf_core/caf/expected.hpp
View file @
94f186a5
...
...
@@ -24,6 +24,7 @@
#include <new>
#include <memory>
#include <ostream>
#include <type_traits>
#include "caf/unit.hpp"
...
...
@@ -396,6 +397,13 @@ private:
caf
::
error
error_
;
};
template
<
class
T
>
auto
to_string
(
const
expected
<
T
>&
x
)
->
decltype
(
to_string
(
*
x
))
{
if
(
x
)
return
to_string
(
*
x
);
return
"!"
+
to_string
(
x
.
error
());
}
/// @cond PRIVATE
/// Assigns the value of `expr` (which must return an `expected`)
/// to a new variable named `var` or throws a `std::runtime_error` on error.
...
...
@@ -410,4 +418,18 @@ private:
}
// namespace caf
namespace
std
{
template
<
class
T
>
auto
operator
<<
(
ostream
&
oss
,
const
caf
::
expected
<
T
>&
x
)
->
decltype
(
oss
<<
*
x
)
{
if
(
x
)
oss
<<
*
x
;
else
oss
<<
"!"
<<
to_string
(
x
.
error
());
return
oss
;
}
}
// namespace std
#endif
libcaf_core/caf/function_view.hpp
View file @
94f186a5
...
...
@@ -32,6 +32,8 @@ namespace caf {
template
<
class
T
>
class
function_view_storage
{
public:
using
type
=
function_view_storage
;
function_view_storage
(
T
&
storage
)
:
storage_
(
&
storage
)
{
// nop
}
...
...
@@ -47,6 +49,8 @@ private:
template
<
class
...
Ts
>
class
function_view_storage
<
std
::
tuple
<
Ts
...
>>
{
public:
using
type
=
function_view_storage
;
function_view_storage
(
std
::
tuple
<
Ts
...
>&
storage
)
:
storage_
(
&
storage
)
{
// nop
}
...
...
@@ -62,6 +66,8 @@ private:
template
<
>
class
function_view_storage
<
unit_t
>
{
public:
using
type
=
function_view_storage
;
function_view_storage
(
unit_t
&
)
{
// nop
}
...
...
@@ -71,6 +77,25 @@ public:
}
};
struct
function_view_storage_catch_all
{
message
*
storage_
;
function_view_storage_catch_all
(
message
&
ptr
)
:
storage_
(
&
ptr
)
{
// nop
}
result
<
message
>
operator
()(
const
type_erased_tuple
*
x
)
{
*
storage_
=
message
::
from
(
x
);
return
message
{};
}
};
template
<
>
class
function_view_storage
<
message
>
{
public:
using
type
=
catch_all
<
function_view_storage_catch_all
>
;
};
template
<
class
T
>
struct
function_view_flattened_result
{
using
type
=
T
;
...
...
@@ -137,8 +162,6 @@ public:
}
/// Sends a request message to the assigned actor and returns the result.
/// @throws std::runtime_error if no valid actor is assigned or
/// if the request fails
template
<
class
...
Ts
,
class
R
=
typename
function_view_flattened_result
<
...
...
@@ -150,17 +173,19 @@ public:
>::
type
...
>
>::
tuple_type
>::
type
>
R
operator
()(
Ts
&&
...
xs
)
{
expected
<
R
>
operator
()(
Ts
&&
...
xs
)
{
if
(
impl_
.
unsafe
())
CAF_RAISE_ERROR
(
"bad function call"
);
return
sec
::
bad_function_call
;
error
err
;
function_view_result
<
R
>
result
;
function_view_storage
<
R
>
h
{
result
.
value
};
self_
->
request
(
impl_
,
infinite
,
std
::
forward
<
Ts
>
(
xs
)...).
receive
(
h
,
[]
(
error
&
x
)
{
CAF_RAISE_ERROR
(
to_string
(
x
));
}
[
&
](
error
&
x
)
{
err
=
std
::
move
(
x
);
},
typename
function_view_storage
<
R
>::
type
{
result
.
value
}
);
if
(
err
)
return
err
;
return
flatten
(
result
.
value
);
}
...
...
libcaf_core/caf/fwd.hpp
View file @
94f186a5
...
...
@@ -77,6 +77,7 @@ class proxy_registry;
class
continue_helper
;
class
mailbox_element
;
class
message_handler
;
class
scheduled_actor
;
class
sync_timeout_msg
;
class
response_promise
;
class
event_based_actor
;
...
...
@@ -147,6 +148,7 @@ namespace detail {
class
disposer
;
class
message_data
;
class
group_manager
;
class
private_thread
;
class
dynamic_message_data
;
}
// namespace detail
...
...
libcaf_core/caf/is_timeout_or_catch_all.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_IS_TIMEOUT_OR_CATCH_ALL_HPP
#define CAF_IS_TIMEOUT_OR_CATCH_ALL_HPP
#include "caf/catch_all.hpp"
#include "caf/timeout_definition.hpp"
namespace
caf
{
template
<
class
T
>
struct
is_timeout_or_catch_all
:
std
::
false_type
{};
template
<
class
T
>
struct
is_timeout_or_catch_all
<
catch_all
<
T
>>
:
std
::
true_type
{};
template
<
class
T
>
struct
is_timeout_or_catch_all
<
timeout_definition
<
T
>>
:
std
::
true_type
{};
}
// namespace caf
#endif // CAF_IS_TIMEOUT_OR_CATCH_ALL_HPP
libcaf_core/caf/local_actor.hpp
View file @
94f186a5
...
...
@@ -106,8 +106,16 @@ result<message> drop(local_actor*, const type_erased_tuple*);
/// Base class for actors running on this node, either
/// living in an own thread or cooperatively scheduled.
class
local_actor
:
public
monitorable_actor
,
public
resumable
{
class
local_actor
:
public
monitorable_actor
{
public:
// -- static helper functions to implement default handlers ------------------
static
void
default_error_handler
(
local_actor
*
ptr
,
error
&
x
);
static
void
default_down_handler
(
local_actor
*
ptr
,
down_msg
&
x
);
static
void
default_exit_handler
(
local_actor
*
ptr
,
exit_msg
&
x
);
// -- member types -----------------------------------------------------------
using
mailbox_type
=
detail
::
single_reader_queue
<
mailbox_element
,
...
...
@@ -133,6 +141,10 @@ public:
void
on_destroy
()
override
;
// -- pure virtual modifiers -------------------------------------------------
virtual
void
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
)
=
0
;
// -- spawn functions --------------------------------------------------------
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
...
...
@@ -204,44 +216,6 @@ public:
// -- miscellaneous actor operations -----------------------------------------
/// Sets a custom handler for unexpected messages.
inline
void
set_default_handler
(
default_handler
fun
)
{
default_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for error messages.
inline
void
set_error_handler
(
error_handler
fun
)
{
error_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for error messages.
template
<
class
T
>
auto
set_error_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
error
&>
()))
{
set_error_handler
([
fun
](
local_actor
*
,
error
&
x
)
{
fun
(
x
);
});
}
/// Sets a custom handler for down messages.
inline
void
set_down_handler
(
down_handler
fun
)
{
down_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for down messages.
template
<
class
T
>
auto
set_down_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
down_msg
&>
()))
{
set_down_handler
([
fun
](
local_actor
*
,
down_msg
&
x
)
{
fun
(
x
);
});
}
/// Sets a custom handler for error messages.
inline
void
set_exit_handler
(
exit_handler
fun
)
{
exit_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for exit messages.
template
<
class
T
>
auto
set_exit_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
exit_msg
&>
()))
{
set_exit_handler
([
fun
](
local_actor
*
,
exit_msg
&
x
)
{
fun
(
x
);
});
}
/// Returns the execution unit currently used by this actor.
inline
execution_unit
*
context
()
const
{
return
context_
;
...
...
@@ -265,25 +239,6 @@ public:
/// Causes this actor to leave the group `what`.
void
leave
(
const
group
&
what
);
/// Finishes execution of this actor after any currently running
/// message handler is done.
/// This member function clears the behavior stack of the running actor
/// and invokes `on_exit()`. The actors does not finish execution
/// if the implementation of `on_exit()` sets a new behavior.
/// When setting a new behavior in `on_exit()`, one has to make sure
/// to not produce an infinite recursion.
///
/// If `on_exit()` did not set a new behavior, the actor sends an
/// exit message to all of its linked actors, sets its state to exited
/// and finishes execution.
///
/// In case this actor uses the blocking API, this member function unwinds
/// the stack by throwing an `actor_exited` exception.
/// @warning This member function throws immediately in thread-based actors
/// that do not use the behavior stack, i.e., actors that use
/// blocking API calls such as {@link receive()}.
void
quit
(
error
reason
=
error
{});
/// @cond PRIVATE
void
monitor
(
abstract_actor
*
whom
);
...
...
@@ -379,11 +334,6 @@ public:
/// The default implementation throws a `std::logic_error`.
virtual
void
load_state
(
deserializer
&
source
,
const
unsigned
int
version
);
// -- overridden member functions of resumable -------------------------------
subtype_t
subtype
()
const
override
;
resume_result
resume
(
execution_unit
*
,
size_t
)
override
;
// -- here be dragons: end of public interface -------------------------------
...
...
@@ -393,15 +343,8 @@ public:
std
::
pair
<
resumable
::
resume_result
,
invoke_message_result
>
exec_event
(
mailbox_element_ptr
&
ptr
);
// handle `ptr` in an event-based actor, not suitable to be called in a loop
virtual
void
exec_single_event
(
execution_unit
*
ctx
,
mailbox_element_ptr
&
ptr
);
local_actor
(
actor_config
&
sys
);
void
intrusive_ptr_add_ref_impl
()
override
;
void
intrusive_ptr_release_impl
()
override
;
template
<
class
ActorHandle
>
inline
ActorHandle
eval_opts
(
spawn_options
opts
,
ActorHandle
res
)
{
if
(
has_monitor_flag
(
opts
))
{
...
...
@@ -471,7 +414,7 @@ public:
||
!
multiplexed_responses_
.
empty
();
}
virtual
void
initialize
()
=
0
;
virtual
void
initialize
();
// clear behavior stack and call cleanup if actor either has no
// valid behavior left or has set a planned exit reason
...
...
@@ -524,14 +467,6 @@ public:
void
set_multiplexed_response_handler
(
message_id
response_id
,
behavior
bhvr
);
// these functions are dispatched via the actor policies table
void
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
);
using
abstract_actor
::
enqueue
;
void
enqueue
(
mailbox_element_ptr
,
execution_unit
*
)
override
;
mailbox_element_ptr
next_message
();
bool
has_next_message
();
...
...
@@ -588,6 +523,9 @@ protected:
// used for setting custom exit message handlers
exit_handler
exit_handler_
;
// used when detaching actors
detail
::
private_thread
*
private_thread_
;
/// @endcond
private:
...
...
@@ -602,10 +540,6 @@ private:
msg_type
filter_msg
(
mailbox_element
&
node
);
void
handle_response
(
mailbox_element_ptr
&
,
local_actor
::
pending_response
&
);
class
private_thread
;
private_thread
*
private_thread_
;
};
/// A smart pointer to a {@link local_actor} instance.
...
...
libcaf_core/caf/match_case.hpp
View file @
94f186a5
...
...
@@ -129,6 +129,7 @@ public:
param_decay
>::
type
;
/*
static_assert(! std::is_same<pattern, detail::type_list<exit_msg>>::value,
"exit_msg not allowed in message handlers, "
"did you mean to use set_exit_handler()?");
...
...
@@ -136,6 +137,7 @@ public:
static_assert(! std::is_same<pattern, detail::type_list<down_msg>>::value,
"down_msg not allowed in message handlers, "
"did you mean to use set_down_handler()?");
*/
using
decayed_arg_types
=
typename
detail
::
tl_map
<
...
...
libcaf_core/caf/others.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_OTHERS_HPP
#define CAF_OTHERS_HPP
#include <functional>
#include <type_traits>
#include "caf/catch_all.hpp"
namespace
caf
{
struct
others_t
{
constexpr
others_t
()
{
// nop
}
template
<
class
F
>
catch_all
<
F
>
operator
>>
(
F
fun
)
const
{
return
{
fun
};
}
};
constexpr
others_t
others
=
others_t
{};
}
// namespace caf
#endif // CAF_OTHERS_HPP
libcaf_core/caf/response_handle.hpp
View file @
94f186a5
...
...
@@ -23,6 +23,7 @@
#include <type_traits>
#include "caf/sec.hpp"
#include "caf/catch_all.hpp"
#include "caf/message_id.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/continue_helper.hpp"
...
...
@@ -148,21 +149,9 @@ public:
using
error_handler
=
std
::
function
<
void
(
error
&
)
>
;
template
<
class
F
,
class
E
=
detail
::
is_callable_t
<
F
>
>
void
receive
(
F
f
)
{
receive_impl
(
f
);
}
template
<
class
F
,
class
OnError
,
class
E1
=
detail
::
is_callable_t
<
F
>,
class
E2
=
detail
::
is_handler_for_ef
<
OnError
,
error
>>
void
receive
(
F
f
,
OnError
ef
)
{
receive_impl
(
f
,
ef
);
}
private:
template
<
class
F
>
void
receive_impl
(
F
&
f
)
{
class
E
=
detail
::
is_handler_for_ef
<
OnError
,
error
>
>
detail
::
is_callable_t
<
F
>
receive
(
F
f
,
OnError
ef
)
{
static_assert
(
std
::
is_same
<
void
,
typename
detail
::
get_callable_trait
<
F
>::
result_type
...
...
@@ -170,23 +159,25 @@ private:
"response handlers are not allowed to have a return "
"type other than void"
);
detail
::
type_checker
<
Output
,
F
>::
check
();
behavior
tmp
{
std
::
move
(
f
)}
;
self_
->
dequeue
(
tmp
,
mid_
);
typename
Self
::
accept_one_cond
rc
;
self_
->
varargs_receive
(
rc
,
mid_
,
std
::
move
(
f
),
std
::
move
(
ef
)
);
}
template
<
class
F
,
class
OnError
>
void
receive_impl
(
F
&
f
,
OnError
&
ef
)
{
static_assert
(
std
::
is_same
<
void
,
typename
detail
::
get_callable_trait
<
F
>::
result_type
>::
value
,
"response handlers are not allowed to have a return "
"type other than void"
);
detail
::
type_checker
<
Output
,
F
>::
check
();
behavior
tmp
{
std
::
move
(
f
),
std
::
move
(
ef
)}
;
self_
->
dequeue
(
tmp
,
mid_
);
template
<
class
OnError
,
class
F
,
class
E
=
detail
::
is_callable_t
<
F
>
>
detail
::
is_handler_for_ef
<
OnError
,
error
>
receive
(
OnError
ef
,
F
f
)
{
receive
(
std
::
move
(
f
),
std
::
move
(
ef
));
}
template
<
class
OnError
,
class
F
,
class
E
=
detail
::
is_handler_for_ef
<
OnError
,
error
>
>
void
receive
(
OnError
ef
,
catch_all
<
F
>
ca
)
{
typename
Self
::
accept_one_cond
rc
;
self_
->
varargs_receive
(
rc
,
mid_
,
std
::
move
(
ef
),
std
::
move
(
ca
)
);
}
private:
message_id
mid_
;
Self
*
self_
;
};
...
...
libcaf_core/caf/scheduled_actor.hpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#ifndef CAF_ABSTRACT_EVENT_BASED_ACTOR_HPP
#define CAF_ABSTRACT_EVENT_BASED_ACTOR_HPP
#include <type_traits>
#include "caf/fwd.hpp"
#include "caf/extend.hpp"
#include "caf/local_actor.hpp"
#include "caf/actor_marker.hpp"
#include "caf/response_handle.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/mixin/sender.hpp"
#include "caf/mixin/requester.hpp"
#include "caf/mixin/behavior_changer.hpp"
#include "caf/logger.hpp"
namespace
caf
{
/// A cooperatively scheduled, event-based actor implementation. This is the
/// recommended base class for user-defined actors.
/// @extends local_actor
class
scheduled_actor
:
public
local_actor
,
public
resumable
{
public:
// -- constructors and destructors -------------------------------------------
scheduled_actor
(
actor_config
&
cfg
);
~
scheduled_actor
();
// -- overridden modifiers of abstract_actor ---------------------------------
void
enqueue
(
mailbox_element_ptr
ptr
,
execution_unit
*
eu
)
override
;
// -- overridden modifiers of local_actor ------------------------------------
void
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
)
override
;
// -- overridden modifiers of resumable --------------------------------------
subtype_t
subtype
()
const
override
;
void
intrusive_ptr_add_ref_impl
()
override
;
void
intrusive_ptr_release_impl
()
override
;
resume_result
resume
(
execution_unit
*
,
size_t
)
override
;
// -- virtual modifiers ------------------------------------------------------
/// Invoke `ptr`, not suitable to be called in a loop.
virtual
void
exec_single_event
(
execution_unit
*
ctx
,
mailbox_element_ptr
&
ptr
);
// -- modifiers --------------------------------------------------------------
/// Finishes execution of this actor after any currently running
/// message handler is done.
/// This member function clears the behavior stack of the running actor
/// and invokes `on_exit()`. The actors does not finish execution
/// if the implementation of `on_exit()` sets a new behavior.
/// When setting a new behavior in `on_exit()`, one has to make sure
/// to not produce an infinite recursion.
///
/// If `on_exit()` did not set a new behavior, the actor sends an
/// exit message to all of its linked actors, sets its state to exited
/// and finishes execution.
///
/// In case this actor uses the blocking API, this member function unwinds
/// the stack by throwing an `actor_exited` exception.
/// @warning This member function throws immediately in thread-based actors
/// that do not use the behavior stack, i.e., actors that use
/// blocking API calls such as {@link receive()}.
void
quit
(
error
reason
=
error
{});
/// Sets a custom handler for unexpected messages.
inline
void
set_default_handler
(
default_handler
fun
)
{
default_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for error messages.
inline
void
set_error_handler
(
error_handler
fun
)
{
error_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for error messages.
template
<
class
T
>
auto
set_error_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
error
&>
()))
{
set_error_handler
([
fun
](
local_actor
*
,
error
&
x
)
{
fun
(
x
);
});
}
/// Sets a custom handler for down messages.
inline
void
set_down_handler
(
down_handler
fun
)
{
down_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for down messages.
template
<
class
T
>
auto
set_down_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
down_msg
&>
()))
{
set_down_handler
([
fun
](
local_actor
*
,
down_msg
&
x
)
{
fun
(
x
);
});
}
/// Sets a custom handler for error messages.
inline
void
set_exit_handler
(
exit_handler
fun
)
{
exit_handler_
=
std
::
move
(
fun
);
}
/// Sets a custom handler for exit messages.
template
<
class
T
>
auto
set_exit_handler
(
T
fun
)
->
decltype
(
fun
(
std
::
declval
<
exit_msg
&>
()))
{
set_exit_handler
([
fun
](
local_actor
*
,
exit_msg
&
x
)
{
fun
(
x
);
});
}
};
}
// namespace caf
#endif // CAF_ABSTRACT_EVENT_BASED_ACTOR_HPP
libcaf_core/caf/sec.hpp
View file @
94f186a5
...
...
@@ -75,7 +75,9 @@ enum class sec : uint8_t {
/// Middleman could not publish an actor because it was invalid.
cannot_publish_invalid_actor
,
/// A remote spawn failed because the provided types did not match.
cannot_spawn_actor_from_arguments
cannot_spawn_actor_from_arguments
,
/// A function view was called without assigning an actor first.
bad_function_call
};
/// @relates sec
...
...
libcaf_core/caf/typed_actor_view.hpp
View file @
94f186a5
...
...
@@ -20,7 +20,7 @@
#ifndef CAF_TYPED_ACTOR_VIEW_HPP
#define CAF_TYPED_ACTOR_VIEW_HPP
#include "caf/
local
_actor.hpp"
#include "caf/
scheduled
_actor.hpp"
#include "caf/mixin/sender.hpp"
#include "caf/mixin/requester.hpp"
...
...
@@ -34,7 +34,7 @@ class typed_actor_view : public extend<typed_actor_view_base,
typed_actor_view
<
Sigs
...
>>::
template
with
<
mixin
::
sender
,
mixin
::
requester
>
{
public:
typed_actor_view
(
local
_actor
*
selfptr
)
:
self_
(
selfptr
)
{
typed_actor_view
(
scheduled
_actor
*
selfptr
)
:
self_
(
selfptr
)
{
// nop
}
...
...
@@ -96,7 +96,7 @@ public:
}
private:
local
_actor
*
self_
;
scheduled
_actor
*
self_
;
};
}
// namespace caf
...
...
libcaf_core/caf/typed_event_based_actor.hpp
View file @
94f186a5
...
...
@@ -25,6 +25,7 @@
#include "caf/typed_actor.hpp"
#include "caf/actor_system.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/mixin/requester.hpp"
#include "caf/mixin/behavior_changer.hpp"
...
...
@@ -41,7 +42,7 @@ public:
/// implementation with static type-checking.
/// @extends local_actor
template
<
class
...
Sigs
>
class
typed_event_based_actor
:
public
extend
<
local
_actor
,
class
typed_event_based_actor
:
public
extend
<
scheduled
_actor
,
typed_event_based_actor
<
Sigs
...
>
>::
template
with
<
mixin
::
sender
,
mixin
::
requester
,
...
...
@@ -49,7 +50,8 @@ class typed_event_based_actor : public extend<local_actor,
public
statically_typed_actor_base
{
public:
using
super
=
typename
extend
<
local_actor
,
typed_event_based_actor
<
Sigs
...
>>::
template
extend
<
scheduled_actor
,
typed_event_based_actor
<
Sigs
...
>>::
template
with
<
mixin
::
sender
,
mixin
::
requester
,
mixin
::
behavior_changer
>;
explicit
typed_event_based_actor
(
actor_config
&
cfg
)
:
super
(
cfg
)
{
...
...
libcaf_core/src/abstract_coordinator.cpp
View file @
94f186a5
...
...
@@ -29,11 +29,11 @@
#include <condition_variable>
#include "caf/send.hpp"
#include "caf/local_actor.hpp"
#include "caf/actor_system.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/actor_ostream.hpp"
#include "caf/system_messages.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/scheduler/coordinator.hpp"
...
...
@@ -126,8 +126,10 @@ public:
}
if
(
msg_ptr
->
msg
.
match_element
<
exit_msg
>
(
0
))
{
auto
&
em
=
msg_ptr
->
msg
.
get_as
<
exit_msg
>
(
0
);
if
(
em
.
reason
)
quit
(
em
.
reason
);
if
(
em
.
reason
)
{
fail_state
(
em
.
reason
);
return
;
}
}
mfun
(
msg_ptr
->
msg
);
msg_ptr
.
reset
();
...
...
@@ -264,14 +266,8 @@ void printer_loop(blocking_actor* self) {
std
::
cout
<<
line
<<
std
::
flush
;
line
.
clear
();
};
/*
bool running = true;
self->set_exit_handler([&](exit_msg&) {
running = false;
});
self->receive_while([&] { return running; })(
*/
self
->
receive_loop
(
bool
done
=
false
;
self
->
do_receive
(
[
&
](
add_atom
,
actor_id
aid
,
std
::
string
&
str
)
{
if
(
str
.
empty
()
||
aid
==
invalid_actor_id
)
return
;
...
...
@@ -298,8 +294,12 @@ void printer_loop(blocking_actor* self) {
auto
d
=
get_data
(
aid
,
true
);
if
(
d
)
d
->
redirect
=
get_sink_handle
(
self
->
system
(),
fcache
,
fn
,
flag
);
},
[
&
](
exit_msg
&
em
)
{
self
->
fail_state
(
std
::
move
(
em
.
reason
));
done
=
true
;
}
);
)
.
until
([
&
]
{
return
done
;
})
;
}
}
// namespace <anonymous>
...
...
@@ -362,7 +362,7 @@ void abstract_coordinator::cleanup_and_release(resumable* ptr) {
switch
(
ptr
->
subtype
())
{
case
resumable
:
:
scheduled_actor
:
case
resumable
:
:
io_actor
:
{
auto
dptr
=
static_cast
<
local
_actor
*>
(
ptr
);
auto
dptr
=
static_cast
<
scheduled
_actor
*>
(
ptr
);
dummy_unit
dummy
{
dptr
};
dptr
->
cleanup
(
make_error
(
exit_reason
::
user_shutdown
),
&
dummy
);
while
(
!
dummy
.
resumables
.
empty
())
{
...
...
@@ -371,7 +371,7 @@ void abstract_coordinator::cleanup_and_release(resumable* ptr) {
switch
(
sub
->
subtype
())
{
case
resumable
:
:
scheduled_actor
:
case
resumable
:
:
io_actor
:
{
auto
dsub
=
static_cast
<
local
_actor
*>
(
sub
);
auto
dsub
=
static_cast
<
scheduled
_actor
*>
(
sub
);
dsub
->
cleanup
(
make_error
(
exit_reason
::
user_shutdown
),
&
dummy
);
break
;
}
...
...
libcaf_core/src/actor_companion.cpp
View file @
94f186a5
...
...
@@ -50,8 +50,4 @@ void actor_companion::enqueue(strong_actor_ptr src, message_id mid,
enqueue
(
std
::
move
(
ptr
),
eu
);
}
void
actor_companion
::
initialize
()
{
// nop
}
}
// namespace caf
libcaf_core/src/actor_registry.cpp
View file @
94f186a5
...
...
@@ -28,7 +28,6 @@
#include "caf/sec.hpp"
#include "caf/locks.hpp"
#include "caf/logger.hpp"
#include "caf/exception.hpp"
#include "caf/actor_cast.hpp"
#include "caf/attachable.hpp"
#include "caf/exit_reason.hpp"
...
...
libcaf_core/src/actor_system_config.cpp
View file @
94f186a5
...
...
@@ -314,8 +314,10 @@ actor_system_config& actor_system_config::set(const char* cn, config_value cv) {
}
std
::
string
actor_system_config
::
render_sec
(
uint8_t
x
,
atom_value
,
const
message
&
)
{
return
"system_error"
+
deep_to_string_as_tuple
(
static_cast
<
sec
>
(
x
));
const
message
&
xs
)
{
return
"system_error"
+
(
xs
.
empty
()
?
deep_to_string_as_tuple
(
static_cast
<
sec
>
(
x
))
:
deep_to_string_as_tuple
(
static_cast
<
sec
>
(
x
),
xs
));
}
std
::
string
actor_system_config
::
render_exit_reason
(
uint8_t
x
,
atom_value
,
...
...
libcaf_core/src/blocking_actor.cpp
View file @
94f186a5
...
...
@@ -20,17 +20,38 @@
#include "caf/blocking_actor.hpp"
#include "caf/logger.hpp"
#include "caf/exception.hpp"
#include "caf/actor_system.hpp"
#include "caf/actor_registry.hpp"
#include "caf/detail/sync_request_bouncer.hpp"
#include "caf/detail/invoke_result_visitor.hpp"
#include "caf/detail/default_invoke_result_visitor.hpp"
namespace
caf
{
blocking_actor
::
receive_cond
::~
receive_cond
()
{
// nop
}
bool
blocking_actor
::
receive_cond
::
pre
()
{
return
true
;
}
bool
blocking_actor
::
receive_cond
::
post
()
{
return
true
;
}
blocking_actor
::
accept_one_cond
::~
accept_one_cond
()
{
// nop
}
bool
blocking_actor
::
accept_one_cond
::
post
()
{
return
false
;
}
blocking_actor
::
blocking_actor
(
actor_config
&
sys
)
:
super
(
sys
.
add_flag
(
local_actor
::
is_blocking_flag
))
{
set_default_handler
(
skip
);
// nop
}
blocking_actor
::~
blocking_actor
()
{
...
...
@@ -49,6 +70,52 @@ void blocking_actor::enqueue(mailbox_element_ptr ptr, execution_unit*) {
}
}
void
blocking_actor
::
launch
(
execution_unit
*
,
bool
,
bool
hide
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
hide
));
CAF_ASSERT
(
is_blocking
());
is_registered
(
!
hide
);
home_system
().
inc_detached_threads
();
std
::
thread
([](
strong_actor_ptr
ptr
)
{
// actor lives in its own thread
auto
this_ptr
=
ptr
->
get
();
CAF_ASSERT
(
dynamic_cast
<
blocking_actor
*>
(
this_ptr
)
!=
0
);
auto
self
=
static_cast
<
blocking_actor
*>
(
this_ptr
);
error
rsn
;
std
::
exception_ptr
eptr
=
nullptr
;
try
{
self
->
act
();
rsn
=
self
->
fail_state_
;
}
catch
(...)
{
rsn
=
exit_reason
::
unhandled_exception
;
eptr
=
std
::
current_exception
();
}
if
(
eptr
)
{
auto
opt_reason
=
self
->
handle
(
eptr
);
rsn
=
opt_reason
?
*
opt_reason
:
exit_reason
::
unhandled_exception
;
}
try
{
self
->
on_exit
();
}
catch
(...)
{
// simply ignore exception
}
self
->
cleanup
(
std
::
move
(
rsn
),
self
->
context
());
ptr
->
home_system
->
dec_detached_threads
();
},
ctrl
()).
detach
();
}
blocking_actor
::
receive_while_helper
blocking_actor
::
receive_while
(
std
::
function
<
bool
()
>
stmt
)
{
return
{
this
,
stmt
};
}
blocking_actor
::
receive_while_helper
blocking_actor
::
receive_while
(
const
bool
&
ref
)
{
return
receive_while
([
&
]
{
return
ref
;
});
}
void
blocking_actor
::
await_all_other_actors_done
()
{
system
().
registry
().
await_running_count_equal
(
is_registered
()
?
1
:
0
);
}
...
...
@@ -59,39 +126,78 @@ void blocking_actor::act() {
initial_behavior_fac_
(
this
);
}
void
blocking_actor
::
initialize
(
)
{
// nop
void
blocking_actor
::
fail_state
(
error
err
)
{
fail_state_
=
std
::
move
(
err
);
}
void
blocking_actor
::
dequeue
(
behavior
&
bhvr
,
message_id
mid
)
{
void
blocking_actor
::
receive_impl
(
receive_cond
&
rcc
,
message_id
mid
,
detail
::
blocking_behavior
&
bhvr
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
mid
));
// calculate absolute timeout if requested by user
auto
rel_tout
=
bhvr
.
timeout
();
std
::
chrono
::
high_resolution_clock
::
time_point
abs_tout
;
if
(
rel_tout
.
valid
())
{
abs_tout
=
std
::
chrono
::
high_resolution_clock
::
now
();
abs_tout
+=
rel_tout
;
}
// try to dequeue from cache first
if
(
invoke_from_cache
(
bhvr
,
mid
))
if
(
invoke_from_cache
(
bhvr
.
nested
,
mid
))
return
;
uint32_t
timeout_id
=
0
;
if
(
mid
!=
invalid_message_id
)
awaited_responses_
.
emplace_front
(
mid
,
bhvr
);
else
timeout_id
=
request_timeout
(
bhvr
.
timeout
());
if
(
mid
!=
invalid_message_id
&&
!
find_awaited_response
(
mid
))
awaited_responses_
.
emplace_front
(
mid
,
behavior
{});
// read incoming messages
// read incoming messages until we have a match or a timeout
detail
::
default_invoke_result_visitor
visitor
{
this
};
for
(;;)
{
await_data
();
auto
msg
=
next_message
();
switch
(
invoke_message
(
msg
,
bhvr
,
mid
))
{
case
im_success
:
if
(
mid
==
invalid_message_id
)
reset_timeout
(
timeout_id
);
return
;
case
im_skipped
:
if
(
msg
)
push_to_cache
(
std
::
move
(
msg
));
break
;
default:
// delete msg
break
;
}
if
(
!
rcc
.
pre
())
return
;
bool
skipped
;
do
{
skipped
=
false
;
if
(
rel_tout
.
valid
())
{
if
(
!
await_data
(
abs_tout
))
{
bhvr
.
handle_timeout
();
return
;
}
}
else
{
await_data
();
}
auto
ptr
=
next_message
();
CAF_ASSERT
(
ptr
!=
nullptr
);
// skip messages that don't match our message ID
if
(
ptr
->
mid
!=
mid
)
{
push_to_cache
(
std
::
move
(
ptr
));
continue
;
}
ptr
.
swap
(
current_element_
);
switch
(
bhvr
.
nested
(
visitor
,
current_element_
->
msg
))
{
case
match_case
:
:
skip
:
skipped
=
true
;
break
;
default:
break
;
case
match_case
:
:
no_match
:
{
auto
sres
=
bhvr
.
fallback
(
current_element_
->
msg
.
cvals
().
get
());
// when dealing with response messages, there's either a match
// on the first handler or we produce an error to
// get a match on the second (error) handler
if
(
sres
.
flag
!=
rt_skip
)
{
visitor
.
visit
(
sres
);
}
else
if
(
mid
.
valid
())
{
// make new message to replace current_element_->msg
auto
x
=
make_message
(
make_error
(
sec
::
unexpected_response
,
std
::
move
(
current_element_
->
msg
)));
current_element_
->
msg
=
std
::
move
(
x
);
bhvr
.
nested
(
current_element_
->
msg
);
}
else
{
skipped
=
true
;
}
}
}
ptr
.
swap
(
current_element_
);
if
(
skipped
)
push_to_cache
(
std
::
move
(
ptr
));
}
while
(
skipped
);
if
(
!
rcc
.
post
())
return
;
}
}
...
...
@@ -100,7 +206,7 @@ void blocking_actor::await_data() {
mailbox
().
synchronized_await
(
mtx_
,
cv_
);
}
bool
blocking_actor
::
await_data
(
std
::
chrono
::
high_resolution_clock
::
time_point
timeout
)
{
bool
blocking_actor
::
await_data
(
timeout_type
timeout
)
{
if
(
has_next_message
())
return
true
;
return
mailbox
().
synchronized_await
(
mtx_
,
cv_
,
timeout
);
...
...
libcaf_core/src/
exception
.cpp
→
libcaf_core/src/
blocking_behavior
.cpp
View file @
94f186a5
...
...
@@ -17,74 +17,30 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include <sstream>
#include <stdlib.h>
#include "caf/config.hpp"
#include "caf/exception.hpp"
#ifdef CAF_WINDOWS
#include <winerror.h>
#else
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#endif
namespace
{
std
::
string
ae_what
(
caf
::
error
reason
)
{
std
::
ostringstream
oss
;
oss
<<
"actor exited with reason: "
<<
to_string
(
reason
);
return
oss
.
str
();
}
}
// namespace <anonymous>
#include "caf/detail/blocking_behavior.hpp"
namespace
caf
{
namespace
detail
{
caf_exception
::~
caf_exception
()
noexcept
{
// nop
}
caf_exception
::
caf_exception
(
std
::
string
x
)
:
what_
(
std
::
move
(
x
))
{
// nop
}
const
char
*
caf_exception
::
what
()
const
noexcept
{
return
what_
.
c_str
();
}
actor_exited
::~
actor_exited
()
noexcept
{
// nop
}
actor_exited
::
actor_exited
(
error
x
)
:
caf_exception
(
ae_what
(
x
))
{
reason_
=
x
;
}
network_error
::
network_error
(
const
std
::
string
&
x
)
:
caf_exception
(
x
)
{
// nop
}
network_error
::
network_error
(
std
::
string
&&
x
)
:
caf_exception
(
std
::
move
(
x
))
{
blocking_behavior
::~
blocking_behavior
()
{
// nop
}
network_error
::~
network_error
()
noexcept
{
blocking_behavior
::
blocking_behavior
(
behavior
x
)
:
nested
(
std
::
move
(
x
))
{
// nop
}
bind_failure
::
bind_failure
(
const
std
::
string
&
x
)
:
network_error
(
x
)
{
// nop
result
<
message
>
blocking_behavior
::
fallback
(
const
type_erased_tuple
*
)
{
return
skip
;
}
bind_failure
::
bind_failure
(
std
::
string
&&
x
)
:
network_error
(
std
::
move
(
x
)
)
{
// nop
duration
blocking_behavior
::
timeout
(
)
{
return
{};
}
bind_failure
::~
bind_failure
()
noexcept
{
void
blocking_behavior
::
handle_timeout
()
{
// nop
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/default_invoke_result_visitor.cpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include "caf/detail/default_invoke_result_visitor.hpp"
namespace
caf
{
namespace
detail
{
default_invoke_result_visitor
::~
default_invoke_result_visitor
()
{
// nop
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/local_actor.cpp
View file @
94f186a5
This diff is collapsed.
Click to expand it.
libcaf_core/src/private_thread.cpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include "caf/detail/private_thread.hpp"
#include "caf/scheduled_actor.hpp"
namespace
caf
{
namespace
detail
{
private_thread
::
private_thread
(
scheduled_actor
*
self
)
:
self_destroyed_
(
false
),
self_
(
self
),
state_
(
active
),
system_
(
self
->
system
())
{
intrusive_ptr_add_ref
(
self
->
ctrl
());
system_
.
inc_detached_threads
();
}
void
private_thread
::
run
()
{
auto
job
=
const_cast
<
scheduled_actor
*>
(
self_
);
CAF_PUSH_AID
(
job
->
id
());
CAF_LOG_TRACE
(
""
);
scoped_execution_unit
ctx
{
&
job
->
system
()};
auto
max_throughput
=
std
::
numeric_limits
<
size_t
>::
max
();
bool
resume_later
;
for
(;;)
{
state_
=
await_resume_or_shutdown
;
do
{
resume_later
=
false
;
switch
(
job
->
resume
(
&
ctx
,
max_throughput
))
{
case
resumable
:
:
resume_later
:
resume_later
=
true
;
break
;
case
resumable
:
:
done
:
intrusive_ptr_release
(
job
->
ctrl
());
return
;
case
resumable
:
:
awaiting_message
:
intrusive_ptr_release
(
job
->
ctrl
());
break
;
case
resumable
:
:
shutdown_execution_unit
:
return
;
}
}
while
(
resume_later
);
// wait until actor becomes ready again or was destroyed
if
(
!
await_resume
())
return
;
}
}
bool
private_thread
::
await_resume
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
(
mtx_
);
while
(
state_
==
await_resume_or_shutdown
)
cv_
.
wait
(
guard
);
return
state_
==
active
;
}
void
private_thread
::
resume
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
(
mtx_
);
state_
=
active
;
cv_
.
notify_one
();
}
void
private_thread
::
shutdown
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
(
mtx_
);
state_
=
shutdown_requested
;
cv_
.
notify_one
();
}
void
private_thread
::
exec
(
private_thread
*
this_ptr
)
{
this_ptr
->
run
();
// make sure to not destroy the private thread object before the
// detached actor is destroyed and this object is unreachable
this_ptr
->
await_self_destroyed
();
// signalize destruction of detached thread to registry
this_ptr
->
system_
.
dec_detached_threads
();
// done
delete
this_ptr
;
}
void
private_thread
::
notify_self_destroyed
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
(
mtx_
);
self_destroyed_
=
true
;
cv_
.
notify_one
();
}
void
private_thread
::
await_self_destroyed
()
{
std
::
unique_lock
<
std
::
mutex
>
guard
(
mtx_
);
while
(
!
self_destroyed_
)
cv_
.
wait
(
guard
);
}
void
private_thread
::
start
()
{
std
::
thread
{
exec
,
this
}.
detach
();
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/scheduled_actor.cpp
0 → 100644
View file @
94f186a5
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include "caf/scheduled_actor.hpp"
#include "caf/detail/private_thread.hpp"
#include "caf/detail/sync_request_bouncer.hpp"
namespace
caf
{
scheduled_actor
::
scheduled_actor
(
actor_config
&
cfg
)
:
local_actor
(
cfg
)
{
// nop
}
scheduled_actor
::~
scheduled_actor
()
{
// nop
}
void
scheduled_actor
::
enqueue
(
mailbox_element_ptr
ptr
,
execution_unit
*
eu
)
{
CAF_PUSH_AID
(
id
());
CAF_LOG_TRACE
(
CAF_ARG
(
*
ptr
));
CAF_ASSERT
(
ptr
!=
nullptr
);
CAF_ASSERT
(
!
is_blocking
());
auto
mid
=
ptr
->
mid
;
auto
sender
=
ptr
->
sender
;
switch
(
mailbox
().
enqueue
(
ptr
.
release
()))
{
case
detail
:
:
enqueue_result
::
unblocked_reader
:
{
// add a reference count to this actor and re-schedule it
intrusive_ptr_add_ref
(
ctrl
());
if
(
is_detached
())
{
CAF_ASSERT
(
private_thread_
!=
nullptr
);
private_thread_
->
resume
();
}
else
{
if
(
eu
)
eu
->
exec_later
(
this
);
else
home_system
().
scheduler
().
enqueue
(
this
);
}
break
;
}
case
detail
:
:
enqueue_result
::
queue_closed
:
{
if
(
mid
.
is_request
())
{
detail
::
sync_request_bouncer
f
{
exit_reason
()};
f
(
sender
,
mid
);
}
break
;
}
case
detail
:
:
enqueue_result
::
success
:
// enqueued to a running actors' mailbox; nothing to do
break
;
}
}
void
scheduled_actor
::
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
lazy
)
<<
CAF_ARG
(
hide
));
CAF_ASSERT
(
!
is_blocking
());
is_registered
(
!
hide
);
if
(
is_detached
())
{
private_thread_
=
new
detail
::
private_thread
(
this
);
private_thread_
->
start
();
return
;
}
CAF_ASSERT
(
eu
!=
nullptr
);
// do not schedule immediately when spawned with `lazy_init`
// mailbox could be set to blocked
if
(
lazy
&&
mailbox
().
try_block
())
return
;
// scheduler has a reference count to the actor as long as
// it is waiting to get scheduled
intrusive_ptr_add_ref
(
ctrl
());
eu
->
exec_later
(
this
);
}
resumable
::
subtype_t
scheduled_actor
::
subtype
()
const
{
return
resumable
::
scheduled_actor
;
}
void
scheduled_actor
::
intrusive_ptr_add_ref_impl
()
{
intrusive_ptr_add_ref
(
ctrl
());
}
void
scheduled_actor
::
intrusive_ptr_release_impl
()
{
intrusive_ptr_release
(
ctrl
());
}
resumable
::
resume_result
scheduled_actor
::
resume
(
execution_unit
*
eu
,
size_t
max_throughput
)
{
CAF_PUSH_AID
(
id
());
CAF_LOG_TRACE
(
""
);
CAF_ASSERT
(
eu
!=
nullptr
);
CAF_ASSERT
(
!
is_blocking
());
context
(
eu
);
if
(
is_initialized
()
&&
(
!
has_behavior
()
||
is_terminated
()))
{
CAF_LOG_DEBUG_IF
(
!
has_behavior
(),
"resume called on an actor without behavior"
);
CAF_LOG_DEBUG_IF
(
is_terminated
(),
"resume called on a terminated actor"
);
return
resumable
::
done
;
}
std
::
exception_ptr
eptr
=
nullptr
;
try
{
if
(
!
is_initialized
())
{
initialize
();
if
(
finished
())
{
CAF_LOG_DEBUG
(
"actor_done() returned true right "
<<
"after make_behavior()"
);
return
resumable
::
resume_result
::
done
;
}
else
{
CAF_LOG_DEBUG
(
"initialized actor:"
<<
CAF_ARG
(
name
()));
}
}
int
handled_msgs
=
0
;
auto
reset_timeout_if_needed
=
[
&
]
{
if
(
handled_msgs
>
0
&&
!
bhvr_stack_
.
empty
())
{
request_timeout
(
bhvr_stack_
.
back
().
timeout
());
}
};
for
(
size_t
i
=
0
;
i
<
max_throughput
;
++
i
)
{
auto
ptr
=
next_message
();
if
(
ptr
)
{
auto
res
=
exec_event
(
ptr
);
if
(
res
.
first
==
resumable
::
resume_result
::
done
)
return
resumable
::
resume_result
::
done
;
if
(
res
.
second
==
im_success
)
++
handled_msgs
;
}
else
{
CAF_LOG_DEBUG
(
"no more element in mailbox; going to block"
);
reset_timeout_if_needed
();
if
(
mailbox
().
try_block
())
return
resumable
::
awaiting_message
;
CAF_LOG_DEBUG
(
"try_block() interrupted by new message"
);
}
}
reset_timeout_if_needed
();
if
(
!
has_next_message
()
&&
mailbox
().
try_block
())
return
resumable
::
awaiting_message
;
// time's up
return
resumable
::
resume_later
;
}
catch
(
std
::
exception
&
e
)
{
CAF_LOG_INFO
(
"actor died because of an exception, what: "
<<
e
.
what
());
static_cast
<
void
>
(
e
);
// keep compiler happy when not logging
if
(
!
is_terminated
())
quit
(
exit_reason
::
unhandled_exception
);
eptr
=
std
::
current_exception
();
}
catch
(...)
{
CAF_LOG_INFO
(
"actor died because of an unknown exception"
);
if
(
!
is_terminated
())
quit
(
exit_reason
::
unhandled_exception
);
eptr
=
std
::
current_exception
();
}
if
(
eptr
)
{
auto
opt_reason
=
handle
(
eptr
);
if
(
opt_reason
)
{
// use exit reason defined by custom handler
quit
(
*
opt_reason
);
}
}
if
(
!
finished
())
{
// actor has been "revived", try running it again later
return
resumable
::
resume_later
;
}
return
resumable
::
done
;
}
void
scheduled_actor
::
quit
(
error
x
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
fail_state_
=
std
::
move
(
x
);
is_terminated
(
true
);
}
void
scheduled_actor
::
exec_single_event
(
execution_unit
*
ctx
,
mailbox_element_ptr
&
ptr
)
{
CAF_ASSERT
(
ctx
!=
nullptr
);
context
(
ctx
);
if
(
!
is_initialized
())
{
CAF_LOG_DEBUG
(
"initialize actor"
);
initialize
();
if
(
finished
())
{
CAF_LOG_DEBUG
(
"actor_done() returned true right "
<<
"after make_behavior()"
);
return
;
}
}
if
(
!
has_behavior
()
||
is_terminated
())
{
CAF_LOG_DEBUG_IF
(
!
has_behavior
(),
"resume called on an actor without behavior"
);
CAF_LOG_DEBUG_IF
(
is_terminated
(),
"resume called on a terminated actor"
);
return
;
}
try
{
exec_event
(
ptr
);
}
catch
(...)
{
CAF_LOG_INFO
(
"broker died because of an exception"
);
auto
eptr
=
std
::
current_exception
();
auto
opt_reason
=
this
->
handle
(
eptr
);
if
(
opt_reason
)
quit
(
*
opt_reason
);
}
}
}
// namespace caf
libcaf_core/src/sec.cpp
View file @
94f186a5
...
...
@@ -46,14 +46,15 @@ const char* sec_strings[] = {
"invalid_argument"
,
"invalid_protocol_family"
,
"cannot_publish_invalid_actor"
,
"cannot_spawn_actor_from_arguments"
"cannot_spawn_actor_from_arguments"
,
"bad_function_call"
};
}
// namespace <anonymous>
const
char
*
to_string
(
sec
x
)
{
auto
index
=
static_cast
<
size_t
>
(
x
);
if
(
index
>
static_cast
<
size_t
>
(
sec
::
cannot_spawn_actor_from_arguments
))
if
(
index
>
static_cast
<
size_t
>
(
sec
::
bad_function_call
))
return
"<unknown>"
;
return
sec_strings
[
index
];
}
...
...
libcaf_core/test/actor_factory.cpp
View file @
94f186a5
...
...
@@ -78,6 +78,7 @@ CAF_TEST(fun_no_args) {
};
cfg
.
add_actor_type
(
"test_actor"
,
test_actor_one_arg
);
test_spawn
(
make_message
());
CAF_MESSAGE
(
"test_spawn done"
);
}
CAF_TEST
(
fun_no_args_selfptr
)
{
...
...
libcaf_core/test/actor_pool.cpp
View file @
94f186a5
...
...
@@ -73,6 +73,10 @@ struct fixture {
}
};
void
handle_err
(
const
error
&
err
)
{
throw
std
::
runtime_error
(
"AUT responded with an error: "
+
to_string
(
err
));
}
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
actor_pool_tests
,
fixture
)
...
...
@@ -90,7 +94,8 @@ CAF_TEST(round_robin_actor_pool) {
auto
sender
=
actor_cast
<
strong_actor_ptr
>
(
self
->
current_sender
());
CAF_REQUIRE
(
sender
);
workers
.
push_back
(
actor_cast
<
actor
>
(
std
::
move
(
sender
)));
}
},
handle_err
);
}
CAF_CHECK_EQUAL
(
workers
.
size
(),
6u
);
...
...
@@ -101,7 +106,8 @@ CAF_TEST(round_robin_actor_pool) {
std
::
sort
(
ws
.
begin
(),
ws
.
end
());
CAF_REQUIRE_EQUAL
(
workers
.
size
(),
ws
.
size
());
CAF_CHECK
(
std
::
equal
(
workers
.
begin
(),
workers
.
end
(),
ws
.
begin
()));
}
},
handle_err
);
anon_send_exit
(
workers
.
back
(),
exit_reason
::
user_shutdown
);
self
->
wait_for
(
workers
.
back
());
...
...
@@ -120,7 +126,8 @@ CAF_TEST(round_robin_actor_pool) {
// wait a bit until polling again
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
5
));
}
}
},
handle_err
);
}
CAF_REQUIRE
(
success
);
...
...
@@ -160,7 +167,8 @@ CAF_TEST(random_actor_pool) {
self
->
request
(
pool
,
std
::
chrono
::
milliseconds
(
250
),
1
,
2
).
receive
(
[
&
](
int
res
)
{
CAF_CHECK_EQUAL
(
res
,
3
);
}
},
handle_err
);
}
self
->
send_exit
(
pool
,
exit_reason
::
user_shutdown
);
...
...
@@ -192,12 +200,14 @@ CAF_TEST(split_join_actor_pool) {
self
->
request
(
pool
,
infinite
,
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
,
5
}).
receive
(
[
&
](
int
res
)
{
CAF_CHECK_EQUAL
(
res
,
15
);
}
},
handle_err
);
self
->
request
(
pool
,
infinite
,
std
::
vector
<
int
>
{
6
,
7
,
8
,
9
,
10
}).
receive
(
[
&
](
int
res
)
{
CAF_CHECK_EQUAL
(
res
,
40
);
}
},
handle_err
);
self
->
send_exit
(
pool
,
exit_reason
::
user_shutdown
);
}
...
...
libcaf_core/test/actor_termination.cpp
View file @
94f186a5
...
...
@@ -46,14 +46,12 @@ struct fixture {
:
scoped_self
(
system
),
mirror
(
system
.
spawn
(
mirror_impl
)),
testee
(
unsafe_actor_handle_init
)
{
scoped_self
->
set_down_handler
([](
local_actor
*
,
down_msg
&
dm
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
normal
);
});
// nop
}
template
<
class
...
Ts
>
void
spawn
(
Ts
&&
...
xs
)
{
testee
=
scoped_self
->
spawn
<
monitored
>
(
std
::
forward
<
Ts
>
(
xs
)...);
testee
=
scoped_self
->
spawn
(
std
::
forward
<
Ts
>
(
xs
)...);
}
~
fixture
()
{
...
...
libcaf_core/test/adapter.cpp
View file @
94f186a5
...
...
@@ -52,6 +52,10 @@ struct fixture {
scoped_actor
self
{
system
,
true
};
};
void
handle_err
(
const
error
&
err
)
{
throw
std
::
runtime_error
(
"AUT responded with an error: "
+
to_string
(
err
));
}
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
adapter_tests
,
fixture
)
...
...
@@ -130,12 +134,14 @@ CAF_TEST(partial_currying) {
self
->
request
(
bound
,
infinite
,
2.0
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
2.0
);
}
},
handle_err
);
self
->
request
(
bound
,
infinite
,
10
).
receive
(
[](
int
y
)
{
CAF_CHECK_EQUAL
(
y
,
10
);
}
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
...
...
@@ -146,7 +152,8 @@ CAF_TEST(full_currying) {
self
->
request
(
bound
,
infinite
,
message
{}).
receive
(
[](
int
v
)
{
CAF_CHECK_EQUAL
(
v
,
2
);
}
},
handle_err
);
anon_send_exit
(
bound
,
exit_reason
::
kill
);
anon_send_exit
(
dbl_actor
,
exit_reason
::
kill
);
...
...
@@ -178,12 +185,14 @@ CAF_TEST(type_safe_currying) {
self
->
request
(
bound
,
infinite
,
2.0
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
2.0
);
}
},
handle_err
);
self
->
request
(
bound
,
infinite
,
10
).
receive
(
[](
int
y
)
{
CAF_CHECK_EQUAL
(
y
,
10
);
}
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
...
...
@@ -205,7 +214,8 @@ CAF_TEST(reordering) {
self
->
request
(
bound
,
infinite
,
2.0
,
10
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
20.0
);
}
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
...
...
@@ -231,7 +241,8 @@ CAF_TEST(type_safe_reordering) {
self
->
request
(
bound
,
infinite
,
2.0
,
10
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
20.0
);
}
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
...
...
libcaf_core/test/atom.cpp
View file @
94f186a5
...
...
@@ -92,7 +92,8 @@ CAF_TEST(receive_atoms) {
[
&
](
a_atom
,
b_atom
,
c_atom
,
float
value
)
{
matched_pattern
[
2
]
=
true
;
CAF_CHECK_EQUAL
(
value
,
23.
f
);
});
}
);
}
CAF_CHECK
(
matched_pattern
[
0
]
&&
matched_pattern
[
1
]
&&
matched_pattern
[
2
]);
self
->
receive
(
...
...
@@ -129,6 +130,9 @@ CAF_TEST(request_atom_constants) {
self
->
request
(
tst
,
infinite
,
abc_atom
::
value
).
receive
(
[](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
42
);
},
[
&
](
error
&
err
)
{
CAF_FAIL
(
"err: "
<<
system
.
render
(
err
));
}
);
}
...
...
libcaf_core/test/composable_behavior.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
std
;
using
namespace
caf
;
...
...
@@ -230,9 +233,14 @@ CAF_TEST(param_detaching) {
// to a test before moving to the second test; otherwise, reference counts
// can diverge from what we expect
auto
ping_pong
=
[
&
]
{
self
->
request
(
dict
,
infinite
,
ping_atom
::
value
).
receive
([](
pong_atom
)
{
// nop
});
self
->
request
(
dict
,
infinite
,
ping_atom
::
value
).
receive
(
[](
pong_atom
)
{
// nop
},
[
&
](
error
&
err
)
{
CAF_FAIL
(
"error: "
<<
system
.
render
(
err
));
}
);
};
// Using CAF is the key to success!
counting_string
key
=
"CAF"
;
...
...
@@ -255,7 +263,8 @@ CAF_TEST(param_detaching) {
CAF_CHECK_EQUAL
(
counting_strings_created
.
load
(),
9
);
CAF_CHECK_EQUAL
(
counting_strings_moved
.
load
(),
2
);
CAF_CHECK_EQUAL
(
counting_strings_destroyed
.
load
(),
2
);
}
},
ERROR_HANDLER
);
// send put message to dictionary again
self
->
request
(
dict
,
infinite
,
put_msg
).
receive
(
...
...
@@ -265,7 +274,8 @@ CAF_TEST(param_detaching) {
CAF_CHECK_EQUAL
(
counting_strings_created
.
load
(),
9
);
CAF_CHECK_EQUAL
(
counting_strings_moved
.
load
(),
2
);
CAF_CHECK_EQUAL
(
counting_strings_destroyed
.
load
(),
2
);
}
},
ERROR_HANDLER
);
// alter our initial put, this time moving it to the dictionary
put_msg
.
get_as_mutable
<
counting_string
>
(
1
)
=
"neverlord"
;
...
...
@@ -279,7 +289,8 @@ CAF_TEST(param_detaching) {
CAF_CHECK_EQUAL
(
counting_strings_created
.
load
(),
11
);
CAF_CHECK_EQUAL
(
counting_strings_moved
.
load
(),
4
);
CAF_CHECK_EQUAL
(
counting_strings_destroyed
.
load
(),
4
);
}
},
ERROR_HANDLER
);
// finally, check for original key
self
->
request
(
dict
,
infinite
,
std
::
move
(
get_msg
)).
receive
(
...
...
@@ -292,7 +303,8 @@ CAF_TEST(param_detaching) {
CAF_CHECK_EQUAL
(
counting_strings_moved
.
load
(),
5
);
CAF_CHECK_EQUAL
(
counting_strings_destroyed
.
load
(),
6
);
CAF_CHECK_EQUAL
(
str
,
"success"
);
}
},
ERROR_HANDLER
);
// temporary of our handler is destroyed
CAF_CHECK_EQUAL
(
counting_strings_destroyed
.
load
(),
7
);
...
...
libcaf_core/test/custom_exception_handler.cpp
View file @
94f186a5
...
...
@@ -73,19 +73,5 @@ CAF_TEST(test_custom_exception_handler) {
auto
testee3
=
self
->
spawn
<
exception_testee
,
monitored
>
();
self
->
send
(
testee3
,
"foo"
);
// receive all down messages
self
->
set_down_handler
([
&
](
down_msg
&
dm
)
{
if
(
dm
.
source
==
testee1
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
normal
);
}
else
if
(
dm
.
source
==
testee2
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unhandled_exception
);
}
else
if
(
dm
.
source
==
testee3
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
remote_link_unreachable
);
}
else
{
throw
std
::
runtime_error
(
"received message from unexpected source"
);
}
});
self
->
wait_for
(
testee1
,
testee2
,
testee3
);
}
libcaf_core/test/dynamic_spawn.cpp
View file @
94f186a5
...
...
@@ -141,12 +141,19 @@ public:
}
void
act
()
override
{
receive_loop
(
bool
running
=
true
;
receive_while
(
running
)
(
[
&
](
int
)
{
wait4float
();
},
[
&
](
get_atom
)
{
return
"wait4int"
;
},
[
&
](
exit_msg
&
em
)
{
if
(
em
.
reason
)
{
fail_state
(
std
::
move
(
em
.
reason
));
running
=
false
;
}
}
);
}
...
...
@@ -484,13 +491,8 @@ typed_testee::behavior_type testee() {
CAF_TEST
(
typed_await
)
{
scoped_actor
self
{
system
};
auto
x
=
system
.
spawn
(
testee
);
self
->
request
(
x
,
infinite
,
abc_atom
::
value
).
receive
(
[](
const
std
::
string
&
str
)
{
CAF_CHECK_EQUAL
(
str
,
"abc"
);
}
);
self
->
send_exit
(
x
,
exit_reason
::
user_shutdown
);
auto
f
=
make_function_view
(
system
.
spawn
(
testee
));
CAF_CHECK_EQUAL
(
f
(
abc_atom
::
value
),
"abc"
);
}
// tests attach_functor() inside of an actor's constructor
...
...
@@ -604,28 +606,18 @@ CAF_TEST(custom_exception_handler) {
self
->
send
(
testee3
,
"foo"
);
// receive all down messages
int
downs_received
=
0
;
self
->
set_down_handler
([
&
](
down_msg
&
dm
)
{
if
(
dm
.
source
==
testee1
)
{
++
downs_received
;
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unhandled_exception
);
}
else
if
(
dm
.
source
==
testee2
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unknown
);
++
downs_received
;
}
else
if
(
dm
.
source
==
testee3
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unhandled_exception
);
++
downs_received
;
self
->
receive_for
(
downs_received
,
3
)
(
[
&
](
down_msg
&
dm
)
{
if
(
dm
.
source
==
testee1
)
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unhandled_exception
);
else
if
(
dm
.
source
==
testee2
)
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unknown
);
else
if
(
dm
.
source
==
testee3
)
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
unhandled_exception
);
else
throw
std
::
runtime_error
(
"received message from unexpected source"
);
}
else
{
throw
std
::
runtime_error
(
"received message from unexpected source"
);
}
if
(
downs_received
==
3
)
self
->
send
(
self
,
message
{});
});
// this exploits the fact that down messages are counted by dequeue
behavior
dummy
{[]
{}};
self
->
dequeue
(
dummy
);
);
}
CAF_TEST
(
kill_the_immortal
)
{
...
...
@@ -647,7 +639,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
f
=
[](
event_based_actor
*
self
,
unique_int
ptr
)
->
behavior
{
auto
impl
=
[](
event_based_actor
*
self
,
unique_int
ptr
)
->
behavior
{
auto
i
=
*
ptr
;
return
{
[
=
](
float
)
{
...
...
@@ -656,13 +648,18 @@ CAF_TEST(move_only_argument) {
}
};
};
auto
f
=
make_function_view
(
system
.
spawn
(
impl
,
std
::
move
(
uptr
)));
CAF_CHECK_EQUAL
(
to_string
(
f
(
1.
f
)),
"(42)"
);
/*
auto testee = system.spawn(f, std::move(uptr));
scoped_actor self{system};
self->request(testee, infinite, 1.f).receive(
[](int i) {
CAF_CHECK_EQUAL(i, 42);
}
},
ERROR_HANDLER
);
*/
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/function_view.cpp
View file @
94f186a5
...
...
@@ -98,13 +98,7 @@ CAF_TEST_FIXTURE_SCOPE(function_view_tests, fixture)
CAF_TEST
(
empty_function_fiew
)
{
function_view
<
calculator
>
f
;
try
{
f
(
10
,
20
);
CAF_ERROR
(
"line must be unreachable"
);
}
catch
(
std
::
runtime_error
&
)
{
// nop
}
CAF_CHECK_EQUAL
(
f
(
10
,
20
),
sec
::
bad_function_call
);
}
CAF_TEST
(
single_res_function_view
)
{
...
...
@@ -122,13 +116,7 @@ CAF_TEST(single_res_function_view) {
g
.
assign
(
system
.
spawn
(
multiplier
));
CAF_CHECK_EQUAL
(
g
(
10
,
20
),
200
);
g
.
assign
(
system
.
spawn
(
divider
));
try
{
g
(
1
,
0
);
CAF_ERROR
(
"expected exception"
);
}
catch
(
std
::
runtime_error
&
e
)
{
CAF_MESSAGE
(
e
.
what
());
}
CAF_CHECK
(
!
g
(
1
,
0
));
g
.
assign
(
system
.
spawn
(
divider
));
CAF_CHECK_EQUAL
(
g
(
4
,
2
),
2
);
}
...
...
libcaf_core/test/or_else.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
caf
;
namespace
{
...
...
@@ -49,15 +52,24 @@ struct fixture {
void
run_testee
(
actor
testee
)
{
scoped_actor
self
{
system
};
self
->
request
(
testee
,
infinite
,
a_atom
::
value
).
receive
([](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
1
);
});
self
->
request
(
testee
,
infinite
,
b_atom
::
value
).
receive
([](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
2
);
});
self
->
request
(
testee
,
infinite
,
c_atom
::
value
).
receive
([](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
3
);
});
self
->
request
(
testee
,
infinite
,
a_atom
::
value
).
receive
(
[](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
1
);
},
ERROR_HANDLER
);
self
->
request
(
testee
,
infinite
,
b_atom
::
value
).
receive
(
[](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
2
);
},
ERROR_HANDLER
);
self
->
request
(
testee
,
infinite
,
c_atom
::
value
).
receive
(
[](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
3
);
},
ERROR_HANDLER
);
self
->
send_exit
(
testee
,
exit_reason
::
user_shutdown
);
self
->
await_all_other_actors_done
();
}
...
...
libcaf_core/test/parse_ini.cpp
View file @
94f186a5
...
...
@@ -32,6 +32,9 @@
#include "caf/detail/parse_ini.hpp"
#include "caf/detail/safe_equal.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
caf
;
namespace
{
...
...
@@ -116,7 +119,8 @@ struct fixture {
[
&
](
ok_atom
,
std
::
vector
<
std
::
pair
<
std
::
string
,
message
>>&
msgs
)
{
for
(
auto
&
kvp
:
msgs
)
self
->
send
(
config_server
,
put_atom
::
value
,
kvp
.
first
,
message
{});
}
},
ERROR_HANDLER
);
auto
consume
=
[
&
](
size_t
,
std
::
string
key
,
config_value
&
value
)
{
message_visitor
mv
;
...
...
@@ -159,7 +163,8 @@ struct fixture {
result
=
detail
::
safe_equal
(
what
,
val
);
}
);
}
},
ERROR_HANDLER
);
return
result
;
}
...
...
@@ -192,7 +197,8 @@ struct fixture {
for
(
auto
&
kvp
:
msgs
)
if
(
!
kvp
.
second
.
empty
())
++
result
;
}
},
ERROR_HANDLER
);
return
result
;
}
...
...
libcaf_core/test/request_response.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
std
;
using
namespace
caf
;
...
...
@@ -254,7 +257,8 @@ CAF_TEST(test_void_res) {
self
->
request
(
buddy
,
infinite
,
1
,
2
).
receive
(
[]
{
CAF_MESSAGE
(
"received void res"
);
}
},
ERROR_HANDLER
);
}
...
...
@@ -309,28 +313,25 @@ CAF_TEST(request_float_or_int) {
);
CAF_CHECK_EQUAL
(
invocations
,
2
);
CAF_MESSAGE
(
"trigger sync failure"
);
bool
error_handler_called
=
false
;
bool
int_handler_called
=
false
;
self
->
request
(
foi
,
infinite
,
f_atom
::
value
).
receive
(
[
&
](
int
)
{
CAF_ERROR
(
"int handler called"
);
int_handler_called
=
true
;
CAF_FAIL
(
"int handler called"
);
},
[
&
](
const
error
&
err
)
{
[
&
](
error
&
err
)
{
CAF_MESSAGE
(
"error received"
);
CAF_CHECK_EQUAL
(
err
,
sec
::
unexpected_response
);
error_handler_called
=
true
;
}
);
CAF_CHECK_EQUAL
(
error_handler_called
,
true
);
CAF_CHECK_EQUAL
(
int_handler_called
,
false
);
}
CAF_TEST
(
request_to_mirror
)
{
auto
mirror
=
system
.
spawn
<
sync_mirror
>
();
self
->
request
(
mirror
,
infinite
,
42
).
receive
([
&
](
int
value
)
{
CAF_CHECK_EQUAL
(
value
,
42
);
});
self
->
request
(
mirror
,
infinite
,
42
).
receive
(
[
&
](
int
value
)
{
CAF_CHECK_EQUAL
(
value
,
42
);
},
ERROR_HANDLER
);
}
CAF_TEST
(
request_to_a_fwd2_b_fwd2_c
)
{
...
...
@@ -338,7 +339,8 @@ CAF_TEST(request_to_a_fwd2_b_fwd2_c) {
go_atom
::
value
,
self
->
spawn
<
B
>
(
self
->
spawn
<
C
>
())).
receive
(
[](
ok_atom
)
{
CAF_MESSAGE
(
"received 'ok'"
);
}
},
ERROR_HANDLER
);
}
...
...
@@ -347,7 +349,8 @@ CAF_TEST(request_to_a_fwd2_d_fwd2_c) {
go_atom
::
value
,
self
->
spawn
<
D
>
(
self
->
spawn
<
C
>
())).
receive
(
[](
ok_atom
)
{
CAF_MESSAGE
(
"received 'ok'"
);
}
},
ERROR_HANDLER
);
}
...
...
libcaf_core/test/sequencer.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
caf
;
namespace
{
...
...
@@ -148,7 +151,8 @@ CAF_TEST(dot_composition_1) {
self
->
request
(
first_then_second
,
infinite
,
42
).
receive
(
[](
double
res
)
{
CAF_CHECK_EQUAL
(
res
,
(
42
*
2.0
)
*
(
42
*
4.0
));
}
},
ERROR_HANDLER
);
}
...
...
@@ -161,9 +165,7 @@ CAF_TEST(dot_composition_2) {
[](
int
v
)
{
CAF_CHECK_EQUAL
(
v
,
16
);
},
[](
error
)
{
CAF_CHECK
(
false
);
}
ERROR_HANDLER
);
}
...
...
libcaf_core/test/splitter.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
caf
;
namespace
{
...
...
@@ -104,7 +107,8 @@ CAF_TEST(untyped_splicing) {
CAF_CHECK_EQUAL
(
x
,
(
42.0
*
2.0
));
CAF_CHECK_EQUAL
(
y
,
(
42.0
*
4.0
));
CAF_CHECK_EQUAL
(
z
,
(
23.0
*
42.0
));
}
},
ERROR_HANDLER
);
}
...
...
@@ -122,7 +126,8 @@ CAF_TEST(typed_splicing) {
CAF_CHECK_EQUAL
(
x
,
(
42.0
*
2.0
));
CAF_CHECK_EQUAL
(
y
,
(
42.0
*
4.0
));
CAF_CHECK_EQUAL
(
z
,
(
23.0
*
42.0
));
}
},
ERROR_HANDLER
);
// stage0 and stage1 go out of scope, leaving only the references
// in stages, which will also go out of scope
...
...
libcaf_core/test/stateful_actor.cpp
View file @
94f186a5
...
...
@@ -24,6 +24,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
std
;
using
namespace
caf
;
...
...
@@ -96,7 +99,8 @@ struct fixture {
self
->
request
(
aut
,
infinite
,
get_atom
::
value
).
receive
(
[](
int
x
)
{
CAF_CHECK_EQUAL
(
x
,
20
);
}
},
ERROR_HANDLER
);
}
...
...
@@ -112,7 +116,8 @@ struct fixture {
self
->
request
(
aut
,
infinite
,
get_atom
::
value
).
receive
(
[
&
](
const
string
&
str
)
{
CAF_CHECK_EQUAL
(
str
,
expected
);
}
},
ERROR_HANDLER
);
}
};
...
...
libcaf_core/test/typed_response_promise.cpp
View file @
94f186a5
...
...
@@ -26,6 +26,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
caf
;
namespace
{
...
...
@@ -146,13 +149,15 @@ CAF_TEST(typed_response_promise) {
self
->
request
(
foo
,
infinite
,
get_atom
::
value
,
42
).
receive
(
[](
int
x
)
{
CAF_CHECK_EQUAL
(
x
,
84
);
}
},
ERROR_HANDLER
);
self
->
request
(
foo
,
infinite
,
get_atom
::
value
,
42
,
52
).
receive
(
[](
int
x
,
int
y
)
{
CAF_CHECK_EQUAL
(
x
,
84
);
CAF_CHECK_EQUAL
(
y
,
104
);
}
},
ERROR_HANDLER
);
self
->
request
(
foo
,
infinite
,
get_atom
::
value
,
3.14
,
3.14
).
receive
(
[](
double
x
,
double
y
)
{
...
...
@@ -198,12 +203,13 @@ CAF_TEST(error_response_message) {
CAF_ERROR
(
"unexpected ordinary response message received: "
<<
x
);
}
);
self
->
set_error_handler
([
&
](
error
&
err
)
{
CAF_CHECK_EQUAL
(
err
.
code
(),
static_cast
<
uint8_t
>
(
sec
::
unexpected_message
));
self
->
send
(
self
,
message
{});
});
self
->
send
(
foo
,
get_atom
::
value
,
3.14
);
self
->
receive
([]
{});
self
->
receive
(
[
&
](
error
&
err
)
{
CAF_CHECK_EQUAL
(
err
.
code
(),
static_cast
<
uint8_t
>
(
sec
::
unexpected_message
));
self
->
send
(
self
,
message
{});
}
);
}
// verify that delivering to a satisfied promise has no effect
...
...
libcaf_core/test/typed_spawn.cpp
View file @
94f186a5
...
...
@@ -29,6 +29,9 @@
#include "caf/all.hpp"
#define ERROR_HANDLER \
[&](error& err) { CAF_FAIL(system.render(err)); }
using
namespace
std
;
using
namespace
caf
;
...
...
@@ -321,12 +324,14 @@ struct fixture {
self
->
request
(
ts
,
infinite
,
my_request
{
10
,
20
}).
receive
(
[](
bool
value
)
{
CAF_CHECK_EQUAL
(
value
,
false
);
}
},
ERROR_HANDLER
);
self
->
request
(
ts
,
infinite
,
my_request
{
0
,
0
}).
receive
(
[](
bool
value
)
{
CAF_CHECK_EQUAL
(
value
,
true
);
}
},
ERROR_HANDLER
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
2u
);
auto
c1
=
self
->
spawn
(
client
,
self
,
ts
);
...
...
@@ -408,7 +413,8 @@ CAF_TEST(string_delegator_chain) {
self
->
request
(
aut
,
infinite
,
"Hello World!"
).
receive
(
[](
const
string
&
answer
)
{
CAF_CHECK_EQUAL
(
answer
,
"!dlroW olleH"
);
}
},
ERROR_HANDLER
);
}
...
...
@@ -431,7 +437,8 @@ CAF_TEST(maybe_string_delegator_chain) {
self
->
request
(
aut
,
infinite
,
"abcd"
).
receive
(
[](
ok_atom
,
const
string
&
str
)
{
CAF_CHECK_EQUAL
(
str
,
"dcba"
);
}
},
ERROR_HANDLER
);
}
...
...
libcaf_io/caf/io/abstract_broker.hpp
View file @
94f186a5
...
...
@@ -23,7 +23,7 @@
#include <vector>
#include <unordered_map>
#include "caf/
local
_actor.hpp"
#include "caf/
scheduled
_actor.hpp"
#include "caf/prohibit_top_level_spawn_marker.hpp"
#include "caf/detail/intrusive_partitioned_list.hpp"
...
...
@@ -74,7 +74,7 @@ class middleman;
/// A broker mediates between actor systems and other components in the network.
/// @ingroup Broker
class
abstract_broker
:
public
local
_actor
,
class
abstract_broker
:
public
scheduled
_actor
,
public
prohibit_top_level_spawn_marker
{
public:
virtual
~
abstract_broker
();
...
...
@@ -83,15 +83,25 @@ public:
friend
class
scribe
;
friend
class
doorman
;
void
enqueue
(
strong_actor_ptr
,
message_id
,
message
,
execution_unit
*
)
override
;
// -- overridden modifiers of abstract_actor ---------------------------------
void
enqueue
(
mailbox_element_ptr
,
execution_unit
*
)
override
;
/// Called after this broker has finished execution.
void
enqueue
(
strong_actor_ptr
,
message_id
,
message
,
execution_unit
*
)
override
;
// -- overridden modifiers of local_actor ------------------------------------
void
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
)
override
;
// -- overridden modifiers of abstract_broker --------------------------------
bool
cleanup
(
error
&&
reason
,
execution_unit
*
host
)
override
;
/// Starts running this broker in the `middleman`.
void
launch
(
execution_unit
*
eu
,
bool
lazy
,
bool
hide
);
// -- overridden modifiers of resumable --------------------------------------
resume_result
resume
(
execution_unit
*
,
size_t
)
override
;
// -- modifiers --------------------------------------------------------------
/// Modifies the receive policy for given connection.
/// @param hdl Identifies the affected connection.
...
...
@@ -110,14 +120,6 @@ public:
/// Sends the content of the buffer for given connection.
void
flush
(
connection_handle
hdl
);
/// Returns the number of open connections.
inline
size_t
num_connections
()
const
{
return
scribes_
.
size
();
}
/// Returns all handles of all `scribe` instances attached to this broker.
std
::
vector
<
connection_handle
>
connections
()
const
;
/// Returns the middleman instance this broker belongs to.
inline
middleman
&
parent
()
{
return
system
().
middleman
();
...
...
@@ -190,10 +192,6 @@ public:
return
get_map
(
hdl
).
count
(
hdl
)
>
0
;
}
subtype_t
subtype
()
const
override
;
resume_result
resume
(
execution_unit
*
,
size_t
)
override
;
/// @cond PRIVATE
template
<
class
Handle
>
void
erase
(
Handle
hdl
)
{
...
...
@@ -204,8 +202,24 @@ public:
}
/// @endcond
// -- overridden observers of abstract_actor ---------------------------------
const
char
*
name
()
const
override
;
// -- overridden observers of resumable --------------------------------------
subtype_t
subtype
()
const
override
;
// -- observers --------------------------------------------------------------
/// Returns the number of open connections.
inline
size_t
num_connections
()
const
{
return
scribes_
.
size
();
}
/// Returns all handles of all `scribe` instances attached to this broker.
std
::
vector
<
connection_handle
>
connections
()
const
;
protected:
void
init_broker
();
...
...
libcaf_io/caf/io/network/asio_multiplexer_impl.hpp
View file @
94f186a5
...
...
@@ -18,8 +18,6 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/exception.hpp"
#include "caf/io/broker.hpp"
#include "caf/io/middleman.hpp"
...
...
libcaf_io/caf/io/network/default_multiplexer.hpp
View file @
94f186a5
...
...
@@ -28,7 +28,6 @@
#include "caf/config.hpp"
#include "caf/extend.hpp"
#include "caf/exception.hpp"
#include "caf/ref_counted.hpp"
#include "caf/io/fwd.hpp"
...
...
libcaf_io/src/abstract_broker.cpp
View file @
94f186a5
...
...
@@ -43,7 +43,7 @@ void abstract_broker::enqueue(strong_actor_ptr src, message_id mid,
void
abstract_broker
::
enqueue
(
mailbox_element_ptr
ptr
,
execution_unit
*
)
{
CAF_PUSH_AID
(
id
());
local
_actor
::
enqueue
(
std
::
move
(
ptr
),
&
backend
());
scheduled
_actor
::
enqueue
(
std
::
move
(
ptr
),
&
backend
());
}
void
abstract_broker
::
launch
(
execution_unit
*
eu
,
bool
is_lazy
,
bool
is_hidden
)
{
...
...
@@ -198,7 +198,7 @@ resumable::resume_result
abstract_broker
::
resume
(
execution_unit
*
ctx
,
size_t
mt
)
{
CAF_ASSERT
(
ctx
!=
nullptr
);
CAF_ASSERT
(
ctx
==
&
backend
());
return
local
_actor
::
resume
(
ctx
,
mt
);
return
scheduled
_actor
::
resume
(
ctx
,
mt
);
}
const
char
*
abstract_broker
::
name
()
const
{
...
...
@@ -215,7 +215,7 @@ void abstract_broker::init_broker() {
}
abstract_broker
::
abstract_broker
(
actor_config
&
cfg
)
:
local
_actor
(
cfg
)
{
abstract_broker
::
abstract_broker
(
actor_config
&
cfg
)
:
scheduled
_actor
(
cfg
)
{
// nop
}
...
...
libcaf_io/src/basp_broker.cpp
View file @
94f186a5
...
...
@@ -25,7 +25,6 @@
#include "caf/sec.hpp"
#include "caf/send.hpp"
#include "caf/after.hpp"
#include "caf/exception.hpp"
#include "caf/make_counted.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/actor_system_config.hpp"
...
...
libcaf_io/src/default_multiplexer.cpp
View file @
94f186a5
...
...
@@ -21,7 +21,6 @@
#include "caf/config.hpp"
#include "caf/optional.hpp"
#include "caf/exception.hpp"
#include "caf/make_counted.hpp"
#include "caf/actor_system_config.hpp"
...
...
@@ -93,6 +92,7 @@ bool cc_valid_socket(caf::io::network::native_socket fd) {
fun_name, last_socket_error_as_string())
// calls a C functions and calls exit() if `predicate(var)` returns false
#ifdef CAF_WINDOWS
#define CALL_CRITICAL_CFUN(var, predicate, funname, expr) \
auto var = expr; \
if (! predicate(var)) { \
...
...
@@ -100,6 +100,7 @@ bool cc_valid_socket(caf::io::network::native_socket fd) {
__FILE__, __LINE__, funname, last_socket_error_as_string().c_str());\
abort(); \
} static_cast<void>(0)
#endif // CAF_WINDOWS
}
// namespace <anonymous>
...
...
libcaf_io/src/middleman.cpp
View file @
94f186a5
...
...
@@ -31,7 +31,6 @@
#include "caf/config.hpp"
#include "caf/logger.hpp"
#include "caf/node_id.hpp"
#include "caf/exception.hpp"
#include "caf/actor_proxy.hpp"
#include "caf/make_counted.hpp"
#include "caf/scoped_actor.hpp"
...
...
@@ -181,16 +180,17 @@ expected<strong_actor_ptr> middleman::remote_actor(std::set<std::string> ifs,
std
::
move
(
host
),
port
).
receive
(
[
&
](
ok_atom
,
const
node_id
&
,
strong_actor_ptr
res
,
std
::
set
<
std
::
string
>&
xs
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
res
)
<<
CAF_ARG
(
xs
));
if
(
!
res
)
{
if
(
!
res
)
{
err
=
make_error
(
sec
::
no_actor_published_at_port
,
"no actor published at port"
,
port
);
return
;
}
if
(
!
(
xs
.
empty
()
&&
ifs
.
empty
())
&&
!
std
::
includes
(
xs
.
begin
(),
xs
.
end
(),
ifs
.
begin
(),
ifs
.
end
()))
{
if
(
ifs
.
empty
()
!=
xs
.
empty
()
||
!
std
::
includes
(
xs
.
begin
(),
xs
.
end
(),
ifs
.
begin
(),
ifs
.
end
()))
{
using
kvpair
=
std
::
pair
<
std
::
string
,
std
::
set
<
std
::
string
>>
;
err
=
make_error
(
sec
::
unexpected_actor_messaging_interface
,
"expected signature:"
,
deep_to_string
(
ifs
),
"found:"
,
deep_to_string
(
xs
));
kvpair
(
"expected"
,
ifs
),
kvpair
(
"found"
,
xs
));
return
;
}
result
.
swap
(
res
);
...
...
@@ -249,7 +249,6 @@ strong_actor_ptr middleman::remote_lookup(atom_value name, const node_id& nid) {
auto
basp
=
named_broker
<
basp_broker
>
(
atom
(
"BASP"
));
strong_actor_ptr
result
;
scoped_actor
self
{
system
(),
true
};
self
->
set_default_handler
(
print_and_drop
);
try
{
self
->
send
(
basp
,
forward_atom
::
value
,
actor_cast
<
strong_actor_ptr
>
(
self
),
nid
,
atom
(
"ConfigServ"
),
...
...
libcaf_io/src/middleman_actor.cpp
View file @
94f186a5
...
...
@@ -27,7 +27,6 @@
#include "caf/actor.hpp"
#include "caf/logger.hpp"
#include "caf/node_id.hpp"
#include "caf/exception.hpp"
#include "caf/actor_proxy.hpp"
#include "caf/typed_event_based_actor.hpp"
...
...
libcaf_io/test/basp.cpp
View file @
94f186a5
...
...
@@ -623,6 +623,9 @@ CAF_TEST(remote_actor_and_send) {
CAF_REQUIRE
(
proxy
!=
nullptr
);
CAF_REQUIRE
(
proxy
==
res
);
result
=
actor_cast
<
actor
>
(
res
);
},
[
&
](
error
&
err
)
{
CAF_FAIL
(
"error: "
<<
system
.
render
(
err
));
}
);
CAF_MESSAGE
(
"send message to proxy"
);
...
...
libcaf_io/test/remote_group.cpp
View file @
94f186a5
...
...
@@ -148,6 +148,9 @@ CAF_TEST(server_side_group_comm) {
group_resolver
->
request
(
server
,
infinite
,
get_group_atom
::
value
).
receive
(
[
&
](
const
group
&
x
)
{
grp
=
x
;
},
[
&
](
error
&
err
)
{
CAF_FAIL
(
"error: "
<<
client_side
.
render
(
err
));
}
);
client_side
.
spawn
(
make_client_behavior
,
server
,
grp
);
...
...
libcaf_io/test/typed_broker.cpp
View file @
94f186a5
...
...
@@ -185,6 +185,9 @@ void run_server(int argc, char** argv) {
child
=
std
::
thread
([
=
]
{
run_client
(
argc
,
argv
,
port
);
});
},
[
&
](
error
&
err
)
{
CAF_FAIL
(
"error: "
<<
system
.
render
(
err
));
}
);
self
->
await_all_other_actors_done
();
...
...
libcaf_io/test/typed_remote_actor.cpp
View file @
94f186a5
...
...
@@ -84,24 +84,16 @@ void run_client(int argc, char** argv, uint16_t port) {
// check whether invalid_argument is thrown
// when trying to connect to get an untyped
// handle to the server
try
{
system
.
middleman
().
remote_actor
(
"127.0.0.1"
,
port
);
}
catch
(
network_error
&
e
)
{
CAF_MESSAGE
(
e
.
what
());
}
auto
res
=
system
.
middleman
().
remote_actor
(
"127.0.0.1"
,
port
);
CAF_REQUIRE
(
!
res
);
CAF_MESSAGE
(
system
.
render
(
res
.
error
()));
CAF_MESSAGE
(
"connect to typed_remote_actor"
);
CAF_EXP_THROW
(
serv
,
system
.
middleman
().
typed_remote_actor
<
server_type
>
(
"127.0.0.1"
,
port
));
scoped_actor
self
{
system
};
self
->
request
(
serv
,
infinite
,
ping
{
42
}).
receive
(
[](
const
pong
&
p
)
{
CAF_CHECK_EQUAL
(
p
.
value
,
42
);
}
);
auto
f
=
make_function_view
(
serv
);
CAF_CHECK_EQUAL
(
f
(
ping
{
42
}),
pong
{
42
});
anon_send_exit
(
serv
,
exit_reason
::
user_shutdown
);
self
->
wait_for
(
serv
);
}
void
run_server
(
int
argc
,
char
**
argv
)
{
...
...
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