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
2ded0d8a
Commit
2ded0d8a
authored
Apr 26, 2017
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add downstream type for multi-lanes
parent
384c78a6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
159 additions
and
0 deletions
+159
-0
libcaf_core/caf/filtering_downstream.hpp
libcaf_core/caf/filtering_downstream.hpp
+159
-0
No files found.
libcaf_core/caf/filtering_downstream.hpp
0 → 100644
View file @
2ded0d8a
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* 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_FILTERING_DOWNSTREAM_HPP
#define CAF_FILTERING_DOWNSTREAM_HPP
#include <map>
#include <tuple>
#include <deque>
#include <vector>
#include <functional>
#include "caf/downstream.hpp"
namespace
caf
{
/// A filtering downstream allows stages to fork into multiple lanes, where
/// each lane carries only a subset of the data. For example, the lane
/// mechanism allows you filter key/value pairs before forwarding them to a set
/// of workers in order to handle only a subset of the overall data on each
/// lane.
template
<
class
T
,
class
Key
,
class
KeyCompare
=
std
::
equal_to
<
Key
>,
size_t
KeyIndex
=
0
>
class
filtering_downstream
:
public
downstream
<
T
>
{
public:
/// Base type.
using
super
=
downstream
<
T
>
;
struct
lane
{
typename
super
::
queue_type
queue
;
typename
super
::
path_ptr_list
paths
;
};
/// Identifies a lane inside the downstream. Filters are kept in sorted order
/// and require `Key` to provide `operator<`.
using
filter
=
std
::
vector
<
Key
>
;
using
lanes_map
=
std
::
map
<
filter
,
lane
>
;
filtering_downstream
(
local_actor
*
ptr
,
const
stream_id
&
sid
,
typename
abstract_downstream
::
policy_ptr
pptr
)
:
super
(
ptr
,
sid
,
std
::
move
(
pptr
))
{
// nop
}
void
broadcast
(
size_t
*
hint
)
override
{
fan_out
();
for
(
auto
&
kvp
:
lanes_
)
{
auto
&
l
=
kvp
.
second
;
auto
chunk
=
super
::
get_chunk
(
l
.
queue
,
hint
?
*
hint
:
super
::
min_credit
(
l
.
paths
));
auto
csize
=
chunk
.
size
();
if
(
csize
==
0
)
continue
;
auto
wrapped_chunk
=
make_message
(
std
::
move
(
chunk
));
for
(
auto
&
x
:
l
.
paths
)
{
x
->
open_credit
-=
csize
;
super
::
send_batch
(
*
x
,
csize
,
wrapped_chunk
);
}
}
}
void
anycast
(
size_t
*
)
override
{
fan_out
();
for
(
auto
&
kvp
:
lanes_
)
{
auto
&
l
=
kvp
.
second
;
super
::
sort_by_credit
(
l
.
paths
);
for
(
auto
&
x
:
l
.
paths
)
{
auto
chunk
=
super
::
get_chunk
(
l
.
queue
,
x
->
open_credit
);
auto
csize
=
chunk
.
size
();
if
(
csize
==
0
)
break
;
x
->
open_credit
-=
csize
;
super
::
send_batch
(
*
x
,
csize
,
std
::
move
(
make_message
(
std
::
move
(
chunk
))));
}
}
}
void
add_lane
(
filter
f
)
{
std
::
sort
(
f
);
lanes_
.
emplace
(
std
::
move
(
f
),
typename
super
::
queue_type
{});
}
/// Sets the filter for `x` to `f` and inserts `x` into the appropriate lane.
/// @pre `x` is not registered on *any* lane
void
set_filter
(
const
strong_actor_ptr
&
x
,
filter
f
)
{
std
::
sort
(
f
.
begin
(),
f
.
end
());
lanes_
[
std
::
move
(
f
)].
paths
.
push_back
(
super
::
find
(
x
));
}
void
update_filter
(
const
strong_actor_ptr
&
x
,
filter
f
)
{
std
::
sort
(
f
.
begin
(),
f
.
end
());
erase_from_lanes
(
x
);
lanes_
[
std
::
move
(
f
)].
paths
.
push_back
(
super
::
find
(
x
));
}
private:
void
erase_from_lanes
(
const
strong_actor_ptr
&
x
)
{
for
(
auto
i
=
lanes_
.
begin
();
i
!=
lanes_
.
end
();
++
i
)
if
(
erase_from_lane
(
i
->
second
,
x
))
{
if
(
i
->
second
.
empty
())
lanes_
.
erase
(
i
);
return
;
}
}
bool
erase_from_lane
(
lane
&
l
,
const
strong_actor_ptr
&
x
)
{
auto
predicate
=
[
&
](
const
typename
super
::
path
*
y
)
{
return
x
==
y
->
hdl
;
};
auto
e
=
l
.
paths
.
end
();
auto
i
=
std
::
find_if
(
l
.
paths
.
begin
(),
e
,
predicate
);
if
(
i
!=
e
)
{
l
.
paths
.
erase
(
i
);
return
true
;
}
return
false
;
}
/// Spreads the content of `buf_` to `lanes_`.
void
fan_out
()
{
for
(
auto
&
kvp
:
lanes_
)
for
(
auto
&
x
:
this
->
buf_
)
if
(
selected
(
kvp
.
first
,
x
))
kvp
.
second
.
queue
.
push_back
(
x
);
this
->
buf_
.
clear
();
}
/// Returns `true` if `x` is selected by `f`, `false` otherwise.
bool
selected
(
const
filter
&
f
,
const
T
&
x
)
{
using
std
::
get
;
for
(
auto
&
key
:
f
)
if
(
cmp_
(
key
,
get
<
KeyIndex
>
(
x
)))
return
true
;
return
false
;
}
lanes_map
lanes_
;
KeyCompare
cmp_
;
};
}
// namespace caf
#endif // CAF_FILTERING_DOWNSTREAM_HPP
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