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
0f3d58c0
Commit
0f3d58c0
authored
Dec 17, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add before_processing overload for responses
parent
24a13d0e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
135 additions
and
96 deletions
+135
-96
libcaf_core/caf/actor_profiler.hpp
libcaf_core/caf/actor_profiler.hpp
+18
-4
libcaf_core/caf/scheduled_actor.hpp
libcaf_core/caf/scheduled_actor.hpp
+13
-3
libcaf_core/src/actor_profiler.cpp
libcaf_core/src/actor_profiler.cpp
+8
-0
libcaf_core/src/raw_event_based_actor.cpp
libcaf_core/src/raw_event_based_actor.cpp
+46
-46
libcaf_core/src/scheduled_actor.cpp
libcaf_core/src/scheduled_actor.cpp
+50
-43
No files found.
libcaf_core/caf/actor_profiler.hpp
View file @
0f3d58c0
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include "caf/config.hpp"
#include "caf/config.hpp"
#include "caf/detail/build_config.hpp"
#include "caf/detail/build_config.hpp"
#include "caf/fwd.hpp"
#include "caf/fwd.hpp"
#include "caf/timestamp.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -47,7 +48,8 @@ public:
...
@@ -47,7 +48,8 @@ public:
/// @thread-safe
/// @thread-safe
virtual
void
remove_actor
(
const
local_actor
&
self
)
=
0
;
virtual
void
remove_actor
(
const
local_actor
&
self
)
=
0
;
/// Called whenever an actor is about to process an element from its mailbox.
/// Called whenever an actor is about to process an asynchronous message from
/// its mailbox.
/// @param self The current actor.
/// @param self The current actor.
/// @param element The current element from the mailbox.
/// @param element The current element from the mailbox.
/// @thread-safe
/// @thread-safe
...
@@ -55,6 +57,18 @@ public:
...
@@ -55,6 +57,18 @@ public:
const
mailbox_element
&
element
)
const
mailbox_element
&
element
)
=
0
;
=
0
;
/// Called whenever an actor is about to process a response message from its
/// mailbox.
/// @param self The current actor.
/// @param element The current element from the mailbox.
/// @param request_id Message ID of the original request.
/// @param send_time The timestamp .
/// @note The default implementation calls `before_processing(self, element)`.
/// @thread-safe
virtual
void
before_processing
(
const
local_actor
&
self
,
const
mailbox_element
&
element
,
message_id
request_id
,
timestamp
send_time
);
/// Called after an actor processed an element from its mailbox.
/// Called after an actor processed an element from its mailbox.
/// @param self The current actor.
/// @param self The current actor.
/// @param result Stores whether the actor consumed, skipped or dropped the
/// @param result Stores whether the actor consumed, skipped or dropped the
...
@@ -93,8 +107,8 @@ public:
...
@@ -93,8 +107,8 @@ public:
};
};
#ifdef CAF_ENABLE_ACTOR_PROFILER
#ifdef CAF_ENABLE_ACTOR_PROFILER
# define CAF_BEFORE_PROCESSING(self,
msg
) \
# define CAF_BEFORE_PROCESSING(self,
...
) \
self->system().profiler_before_processing(*self,
msg
)
self->system().profiler_before_processing(*self,
__VA_ARGS__
)
# define CAF_AFTER_PROCESSING(self, result) \
# define CAF_AFTER_PROCESSING(self, result) \
self->system().profiler_after_processing(*self, result)
self->system().profiler_after_processing(*self, result)
# define CAF_BEFORE_SENDING(self, msg) \
# define CAF_BEFORE_SENDING(self, msg) \
...
@@ -102,7 +116,7 @@ public:
...
@@ -102,7 +116,7 @@ public:
# define CAF_BEFORE_SENDING_SCHEDULED(self, timeout, msg) \
# define CAF_BEFORE_SENDING_SCHEDULED(self, timeout, msg) \
self->system().profiler_before_sending_scheduled(*self, timeout, msg)
self->system().profiler_before_sending_scheduled(*self, timeout, msg)
#else
#else
# define CAF_BEFORE_PROCESSING(self,
msg
) static_cast<void>(0)
# define CAF_BEFORE_PROCESSING(self,
...
) static_cast<void>(0)
# define CAF_AFTER_PROCESSING(self, result) static_cast<void>(0)
# define CAF_AFTER_PROCESSING(self, result) static_cast<void>(0)
# define CAF_BEFORE_SENDING(self, msg) static_cast<void>(0)
# define CAF_BEFORE_SENDING(self, msg) static_cast<void>(0)
# define CAF_BEFORE_SENDING_SCHEDULED(self, timeout, msg) static_cast<void>(0)
# define CAF_BEFORE_SENDING_SCHEDULED(self, timeout, msg) static_cast<void>(0)
...
...
libcaf_core/caf/scheduled_actor.hpp
View file @
0f3d58c0
...
@@ -188,8 +188,17 @@ public:
...
@@ -188,8 +188,17 @@ public:
/// A queue optimized for single-reader-many-writers.
/// A queue optimized for single-reader-many-writers.
using
mailbox_type
=
intrusive
::
fifo_inbox
<
mailbox_policy
>
;
using
mailbox_type
=
intrusive
::
fifo_inbox
<
mailbox_policy
>
;
/// Stores state for handling an outstanding response message.
struct
response_handler
{
/// Stores the callbacks for processing the response.
behavior
bhvr
;
/// Stores when the request was sent.
timestamp
send_time
;
};
/// The message ID of an outstanding response with its callback.
/// The message ID of an outstanding response with its callback.
using
pending_response
=
std
::
pair
<
const
message_id
,
behavio
r
>
;
using
pending_response
=
std
::
pair
<
const
message_id
,
response_handle
r
>
;
/// A pointer to a scheduled actor.
/// A pointer to a scheduled actor.
using
pointer
=
scheduled_actor
*
;
using
pointer
=
scheduled_actor
*
;
...
@@ -688,7 +697,7 @@ public:
...
@@ -688,7 +697,7 @@ public:
}
}
inline
behavior
&
current_behavior
()
{
inline
behavior
&
current_behavior
()
{
return
!
awaited_responses_
.
empty
()
?
awaited_responses_
.
front
().
second
return
!
awaited_responses_
.
empty
()
?
awaited_responses_
.
front
().
second
.
bhvr
:
bhvr_stack_
.
back
();
:
bhvr_stack_
.
back
();
}
}
...
@@ -896,7 +905,8 @@ protected:
...
@@ -896,7 +905,8 @@ protected:
std
::
forward_list
<
pending_response
>
awaited_responses_
;
std
::
forward_list
<
pending_response
>
awaited_responses_
;
/// Stores callbacks for multiplexed responses.
/// Stores callbacks for multiplexed responses.
detail
::
unordered_flat_map
<
message_id
,
behavior
>
multiplexed_responses_
;
detail
::
unordered_flat_map
<
message_id
,
response_handler
>
multiplexed_responses_
;
/// Customization point for setting a default `message` callback.
/// Customization point for setting a default `message` callback.
default_handler
default_handler_
;
default_handler
default_handler_
;
...
...
libcaf_core/src/actor_profiler.cpp
View file @
0f3d58c0
...
@@ -18,10 +18,18 @@
...
@@ -18,10 +18,18 @@
#include "caf/actor_profiler.hpp"
#include "caf/actor_profiler.hpp"
#include "caf/message_id.hpp"
namespace
caf
{
namespace
caf
{
actor_profiler
::~
actor_profiler
()
{
actor_profiler
::~
actor_profiler
()
{
// nop
// nop
}
}
void
actor_profiler
::
before_processing
(
const
local_actor
&
self
,
const
mailbox_element
&
element
,
message_id
,
timestamp
)
{
before_processing
(
self
,
element
);
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/raw_event_based_actor.cpp
View file @
0f3d58c0
...
@@ -30,56 +30,56 @@ raw_event_based_actor::raw_event_based_actor(actor_config& cfg)
...
@@ -30,56 +30,56 @@ raw_event_based_actor::raw_event_based_actor(actor_config& cfg)
invoke_message_result
raw_event_based_actor
::
consume
(
mailbox_element
&
x
)
{
invoke_message_result
raw_event_based_actor
::
consume
(
mailbox_element
&
x
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
current_element_
=
&
x
;
current_element_
=
&
x
;
auto
invoke
=
[](
behavior
&
f
,
mailbox_element
&
in
)
->
bool
{
return
f
(
in
.
content
())
!=
none
;
};
// Short-circuit awaited responses. Don't trigger any logging if we skip here.
if
(
!
awaited_responses_
.
empty
())
{
auto
&
pr
=
awaited_responses_
.
front
();
// Skip all messages until we receive the currently awaited response.
if
(
x
.
mid
!=
pr
.
first
)
return
invoke_message_result
::
skipped
;
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
,
pr
.
first
,
pr
.
second
.
send_time
);
auto
f
=
std
::
move
(
pr
.
second
.
bhvr
);
awaited_responses_
.
pop_front
();
if
(
!
invoke
(
f
,
x
))
{
// Try again with error if first attempt failed.
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
f
(
msg
);
}
CAF_AFTER_PROCESSING
(
this
,
invoke_message_result
::
consumed
);
CAF_LOG_SKIP_OR_FINALIZE_EVENT
(
invoke_message_result
::
consumed
);
return
invoke_message_result
::
consumed
;
}
// Handle multiplexed responses.
if
(
x
.
mid
.
is_response
())
{
auto
mrh
=
multiplexed_responses_
.
find
(
x
.
mid
);
// Neither awaited nor multiplexed, probably an expired timeout. Discard
// without bothering the profiler.
if
(
mrh
==
multiplexed_responses_
.
end
())
{
CAF_LOG_DEBUG
(
"drop unexpected response:"
<<
x
);
return
invoke_message_result
::
dropped
;
}
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
,
mrh
->
first
,
mrth
->
second
.
send_time
);
auto
bhvr
=
std
::
move
(
mrh
->
second
.
bhvr
);
multiplexed_responses_
.
erase
(
mrh
);
if
(
!
invoke
(
bhvr
,
x
))
{
// Try again with error if first attempt failed.
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
bhvr
(
msg
);
}
CAF_AFTER_PROCESSING
(
this
,
invoke_message_result
::
consumed
);
CAF_LOG_SKIP_OR_FINALIZE_EVENT
(
invoke_message_result
::
consumed
);
return
invoke_message_result
::
consumed
;
}
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
);
CAF_BEFORE_PROCESSING
(
this
,
x
);
// Wrap the actual body for the function.
// Wrap the actual body for the function.
auto
body
=
[
this
,
&
x
]
{
auto
body
=
[
this
,
&
x
]
{
// short-circuit awaited responses
if
(
!
awaited_responses_
.
empty
())
{
auto
&
pr
=
awaited_responses_
.
front
();
// skip all messages until we receive the currently awaited response
if
(
x
.
mid
!=
pr
.
first
)
return
invoke_message_result
::
skipped
;
if
(
!
pr
.
second
(
x
.
content
()))
{
// try again with error if first attempt failed
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
pr
.
second
(
msg
);
}
awaited_responses_
.
pop_front
();
return
invoke_message_result
::
consumed
;
}
// handle multiplexed responses
if
(
x
.
mid
.
is_response
())
{
auto
mrh
=
multiplexed_responses_
.
find
(
x
.
mid
);
// neither awaited nor multiplexed, probably an expired timeout
if
(
mrh
==
multiplexed_responses_
.
end
())
return
invoke_message_result
::
dropped
;
if
(
!
mrh
->
second
(
x
.
content
()))
{
// try again with error if first attempt failed
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
mrh
->
second
(
msg
);
}
multiplexed_responses_
.
erase
(
mrh
);
return
invoke_message_result
::
consumed
;
}
auto
&
content
=
x
.
content
();
// handle timeout messages
if
(
x
.
content
().
type_token
()
==
make_type_token
<
timeout_msg
>
())
{
auto
&
tm
=
content
.
get_as
<
timeout_msg
>
(
0
);
auto
tid
=
tm
.
timeout_id
;
CAF_ASSERT
(
x
.
mid
.
is_async
());
if
(
is_active_receive_timeout
(
tid
))
{
CAF_LOG_DEBUG
(
"handle timeout message"
);
if
(
bhvr_stack_
.
empty
())
return
invoke_message_result
::
dropped
;
bhvr_stack_
.
back
().
handle_timeout
();
return
invoke_message_result
::
consumed
;
}
CAF_LOG_DEBUG
(
"dropped expired timeout message"
);
return
invoke_message_result
::
dropped
;
}
// handle everything else as ordinary message
// handle everything else as ordinary message
detail
::
default_invoke_result_visitor
<
event_based_actor
>
visitor
{
this
};
detail
::
default_invoke_result_visitor
<
event_based_actor
>
visitor
{
this
};
bool
skipped
=
false
;
bool
skipped
=
false
;
...
...
libcaf_core/src/scheduled_actor.cpp
View file @
0f3d58c0
...
@@ -534,14 +534,16 @@ void scheduled_actor::add_awaited_response_handler(message_id response_id,
...
@@ -534,14 +534,16 @@ void scheduled_actor::add_awaited_response_handler(message_id response_id,
behavior
bhvr
)
{
behavior
bhvr
)
{
if
(
bhvr
.
timeout
().
valid
())
if
(
bhvr
.
timeout
().
valid
())
request_response_timeout
(
bhvr
.
timeout
(),
response_id
);
request_response_timeout
(
bhvr
.
timeout
(),
response_id
);
awaited_responses_
.
emplace_front
(
response_id
,
std
::
move
(
bhvr
));
awaited_responses_
.
emplace_front
(
response_id
,
response_handler
{
std
::
move
(
bhvr
),
make_timestamp
()});
}
}
void
scheduled_actor
::
add_multiplexed_response_handler
(
message_id
response_id
,
void
scheduled_actor
::
add_multiplexed_response_handler
(
message_id
response_id
,
behavior
bhvr
)
{
behavior
bhvr
)
{
if
(
bhvr
.
timeout
().
valid
())
if
(
bhvr
.
timeout
().
valid
())
request_response_timeout
(
bhvr
.
timeout
(),
response_id
);
request_response_timeout
(
bhvr
.
timeout
(),
response_id
);
multiplexed_responses_
.
emplace
(
response_id
,
std
::
move
(
bhvr
));
multiplexed_responses_
.
emplace
(
response_id
,
response_handler
{
std
::
move
(
bhvr
),
make_timestamp
()});
}
}
scheduled_actor
::
message_category
scheduled_actor
::
message_category
...
@@ -630,51 +632,56 @@ scheduled_actor::categorize(mailbox_element& x) {
...
@@ -630,51 +632,56 @@ scheduled_actor::categorize(mailbox_element& x) {
invoke_message_result
scheduled_actor
::
consume
(
mailbox_element
&
x
)
{
invoke_message_result
scheduled_actor
::
consume
(
mailbox_element
&
x
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
current_element_
=
&
x
;
current_element_
=
&
x
;
auto
invoke
=
[](
behavior
&
f
,
mailbox_element
&
in
)
->
bool
{
return
f
(
in
.
content
())
!=
none
;
};
// Short-circuit awaited responses. Don't trigger any logging if we skip here.
if
(
!
awaited_responses_
.
empty
())
{
auto
&
pr
=
awaited_responses_
.
front
();
// Skip all messages until we receive the currently awaited response.
if
(
x
.
mid
!=
pr
.
first
)
return
invoke_message_result
::
skipped
;
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
,
pr
.
first
,
pr
.
second
.
send_time
);
auto
f
=
std
::
move
(
pr
.
second
.
bhvr
);
awaited_responses_
.
pop_front
();
if
(
!
invoke
(
f
,
x
))
{
// Try again with error if first attempt failed.
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
f
(
msg
);
}
CAF_AFTER_PROCESSING
(
this
,
invoke_message_result
::
consumed
);
CAF_LOG_SKIP_OR_FINALIZE_EVENT
(
invoke_message_result
::
consumed
);
return
invoke_message_result
::
consumed
;
}
// Handle multiplexed responses.
if
(
x
.
mid
.
is_response
())
{
auto
mrh
=
multiplexed_responses_
.
find
(
x
.
mid
);
// Neither awaited nor multiplexed, probably an expired timeout. Discard
// without bothering the profiler.
if
(
mrh
==
multiplexed_responses_
.
end
())
{
CAF_LOG_DEBUG
(
"drop unexpected response:"
<<
x
);
return
invoke_message_result
::
dropped
;
}
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
,
mrh
->
first
,
mrth
->
second
.
send_time
);
auto
bhvr
=
std
::
move
(
mrh
->
second
.
bhvr
);
multiplexed_responses_
.
erase
(
mrh
);
if
(
!
invoke
(
bhvr
,
x
))
{
// Try again with error if first attempt failed.
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
bhvr
(
msg
);
}
CAF_AFTER_PROCESSING
(
this
,
invoke_message_result
::
consumed
);
CAF_LOG_SKIP_OR_FINALIZE_EVENT
(
invoke_message_result
::
consumed
);
return
invoke_message_result
::
consumed
;
}
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_LOG_RECEIVE_EVENT
(
current_element_
);
CAF_BEFORE_PROCESSING
(
this
,
x
);
CAF_BEFORE_PROCESSING
(
this
,
x
);
// Wrap the actual body for the function.
// Wrap the actual body for the function.
auto
body
=
[
this
,
&
x
]
{
auto
body
=
[
this
,
&
x
]
{
// Helper function for dispatching a message to a response handler.
using
ptr_t
=
scheduled_actor
*
;
using
fun_t
=
bool
(
*
)(
ptr_t
,
behavior
&
,
mailbox_element
&
);
auto
ordinary_invoke
=
[](
ptr_t
,
behavior
&
f
,
mailbox_element
&
in
)
->
bool
{
return
f
(
in
.
content
())
!=
none
;
};
auto
select_invoke_fun
=
[
&
]()
->
fun_t
{
return
ordinary_invoke
;
};
// Short-circuit awaited responses.
if
(
!
awaited_responses_
.
empty
())
{
auto
invoke
=
select_invoke_fun
();
auto
&
pr
=
awaited_responses_
.
front
();
// skip all messages until we receive the currently awaited response
if
(
x
.
mid
!=
pr
.
first
)
return
invoke_message_result
::
skipped
;
auto
f
=
std
::
move
(
pr
.
second
);
awaited_responses_
.
pop_front
();
if
(
!
invoke
(
this
,
f
,
x
))
{
// try again with error if first attempt failed
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
f
(
msg
);
}
return
invoke_message_result
::
consumed
;
}
// Handle multiplexed responses.
if
(
x
.
mid
.
is_response
())
{
auto
invoke
=
select_invoke_fun
();
auto
mrh
=
multiplexed_responses_
.
find
(
x
.
mid
);
// neither awaited nor multiplexed, probably an expired timeout
if
(
mrh
==
multiplexed_responses_
.
end
())
return
invoke_message_result
::
dropped
;
auto
bhvr
=
std
::
move
(
mrh
->
second
);
multiplexed_responses_
.
erase
(
mrh
);
if
(
!
invoke
(
this
,
bhvr
,
x
))
{
// try again with error if first attempt failed
auto
msg
=
make_message
(
make_error
(
sec
::
unexpected_response
,
x
.
move_content_to_message
()));
bhvr
(
msg
);
}
return
invoke_message_result
::
consumed
;
}
// Dispatch on the content of x.
// Dispatch on the content of x.
switch
(
categorize
(
x
))
{
switch
(
categorize
(
x
))
{
case
message_category
:
:
skipped
:
case
message_category
:
:
skipped
:
...
...
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