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
5477e042
Commit
5477e042
authored
Apr 02, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix memory leaks
parent
55801c50
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
126 additions
and
6 deletions
+126
-6
libcaf_core/caf/flow/observable.hpp
libcaf_core/caf/flow/observable.hpp
+25
-3
libcaf_core/caf/flow/step.hpp
libcaf_core/caf/flow/step.hpp
+1
-0
libcaf_core/caf/flow/subscription.hpp
libcaf_core/caf/flow/subscription.hpp
+22
-0
libcaf_core/src/flow/subscription.cpp
libcaf_core/src/flow/subscription.cpp
+20
-0
libcaf_core/test/flow/broadcaster.cpp
libcaf_core/test/flow/broadcaster.cpp
+29
-0
libcaf_core/test/flow/concat.cpp
libcaf_core/test/flow/concat.cpp
+2
-0
libcaf_core/test/flow/merge.cpp
libcaf_core/test/flow/merge.cpp
+2
-0
libcaf_core/test/flow/never.cpp
libcaf_core/test/flow/never.cpp
+25
-3
No files found.
libcaf_core/caf/flow/observable.hpp
View file @
5477e042
...
...
@@ -147,6 +147,13 @@ public:
observable
&
operator
=
(
observable
&&
)
noexcept
=
default
;
observable
&
operator
=
(
const
observable
&
)
noexcept
=
default
;
void
dispose
()
{
if
(
pimpl_
)
{
pimpl_
->
dispose
();
pimpl_
=
nullptr
;
}
}
disposable
as_disposable
()
const
&
noexcept
{
return
disposable
{
pimpl_
};
}
...
...
@@ -693,6 +700,7 @@ public:
step
.
on_complete
(
steps
...,
term_
);
};
std
::
apply
(
f
,
steps_
);
sub_
=
nullptr
;
}
}
...
...
@@ -702,6 +710,7 @@ public:
step
.
on_error
(
what
,
steps
...,
term_
);
};
std
::
apply
(
f
,
steps_
);
sub_
=
nullptr
;
}
}
...
...
@@ -2158,11 +2167,15 @@ public:
// -- implementation of disposable::impl -------------------------------------
void
dispose
()
override
{
// nop
if
(
!
disposed_
)
{
disposed_
=
true
;
for
(
auto
&
obs
:
observers_
)
obs
.
on_complete
();
}
}
bool
disposed
()
const
noexcept
override
{
return
true
;
return
disposed_
;
}
void
ref_disposable
()
const
noexcept
override
{
...
...
@@ -2188,11 +2201,20 @@ public:
}
disposable
subscribe
(
observer
<
output_type
>
sink
)
override
{
return
this
->
do_subscribe
(
sink
.
ptr
());
if
(
!
disposed_
)
{
auto
ptr
=
make_counted
<
subscription
::
nop_impl
>
();
sink
.
ptr
()
->
on_subscribe
(
subscription
{
std
::
move
(
ptr
)});
observers_
.
emplace_back
(
sink
);
return
sink
.
as_disposable
();
}
else
{
return
this
->
reject_subscription
(
sink
,
sec
::
disposed
);
}
}
private:
coordinator
*
ctx_
;
bool
disposed_
=
false
;
std
::
vector
<
observer
<
output_type
>>
observers_
;
};
/// An observable with minimal internal logic. Useful for writing unit tests.
...
...
libcaf_core/caf/flow/step.hpp
View file @
5477e042
...
...
@@ -433,6 +433,7 @@ public:
size_t
on_cancel
(
observer_impl_t
*
sink
)
{
if
(
auto
i
=
find
(
sink
);
i
!=
outputs_
.
end
())
{
outputs_
.
erase
(
i
);
// TODO: shut down on last cancel?
push
();
return
next_demand
();
}
else
{
...
...
libcaf_core/caf/flow/subscription.hpp
View file @
5477e042
...
...
@@ -33,6 +33,28 @@ public:
void
dispose
()
final
;
};
/// A trivial subscription type that drops all member function calls.
class
CAF_CORE_EXPORT
nop_impl
final
:
public
ref_counted
,
public
subscription
::
impl
{
public:
// -- friends --------------------------------------------------------------
CAF_INTRUSIVE_PTR_FRIENDS
(
nop_impl
)
bool
disposed
()
const
noexcept
override
;
void
ref_disposable
()
const
noexcept
override
;
void
deref_disposable
()
const
noexcept
override
;
void
cancel
()
override
;
void
request
(
size_t
n
)
override
;
private:
bool
disposed_
=
false
;
};
// -- constructors, destructors, and assignment operators --------------------
explicit
subscription
(
intrusive_ptr
<
impl
>
pimpl
)
noexcept
...
...
libcaf_core/src/flow/subscription.cpp
View file @
5477e042
...
...
@@ -14,4 +14,24 @@ void subscription::impl::dispose() {
cancel
();
}
bool
subscription
::
nop_impl
::
disposed
()
const
noexcept
{
return
disposed_
;
}
void
subscription
::
nop_impl
::
ref_disposable
()
const
noexcept
{
ref
();
}
void
subscription
::
nop_impl
::
deref_disposable
()
const
noexcept
{
deref
();
}
void
subscription
::
nop_impl
::
cancel
()
{
disposed_
=
true
;
}
void
subscription
::
nop_impl
::
request
(
size_t
)
{
// nop
}
}
// namespace caf::flow
libcaf_core/test/flow/broadcaster.cpp
View file @
5477e042
...
...
@@ -25,6 +25,33 @@ struct fixture : test_coordinator_fixture<> {
BEGIN_FIXTURE_SCOPE
(
fixture
)
SCENARIO
(
"a broadcaster pushes items to single subscribers"
)
{
GIVEN
(
"a broadcaster with one source and one sink"
)
{
auto
uut
=
flow
::
make_broadcaster_impl
<
int
>
(
ctx
.
get
());
auto
src
=
flow
::
make_passive_observable
<
int
>
(
ctx
.
get
());
auto
snk
=
flow
::
make_passive_observer
<
int
>
();
src
->
subscribe
(
uut
->
as_observer
());
uut
->
subscribe
(
snk
->
as_observer
());
WHEN
(
"the source emits 10 items"
)
{
THEN
(
"the broadcaster forwards them to its sink"
)
{
snk
->
sub
.
request
(
13
);
ctx
->
run
();
CHECK_EQ
(
src
->
demand
,
13u
);
snk
->
sub
.
request
(
7
);
ctx
->
run
();
CHECK_EQ
(
src
->
demand
,
20u
);
auto
inputs
=
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
};
src
->
push
(
make_span
(
inputs
));
CHECK_EQ
(
src
->
demand
,
10u
);
CHECK_EQ
(
uut
->
buffered
(),
0u
);
CHECK_EQ
(
snk
->
buf
,
std
::
vector
<
int
>
({
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
}));
src
->
complete
();
ctx
->
run
();
}
}
}
}
SCENARIO
(
"a broadcaster pushes items to all subscribers at the same time"
)
{
GIVEN
(
"a broadcaster with one source and three sinks"
)
{
auto
uut
=
flow
::
make_broadcaster_impl
<
int
>
(
ctx
.
get
());
...
...
@@ -64,6 +91,8 @@ SCENARIO("a broadcaster pushes items to all subscribers at the same time") {
snk2
->
sub
.
request
(
14
);
ctx
->
run
();
CHECK_EQ
(
src
->
demand
,
18u
);
src
->
complete
();
ctx
->
run
();
}
}
}
...
...
libcaf_core/test/flow/concat.cpp
View file @
5477e042
...
...
@@ -52,6 +52,8 @@ SCENARIO("concatenate processes inputs sequentially") {
ctx
->
run
();
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
subscribed
);
CHECK
(
snk
->
buf
.
empty
());
uut
->
dispose
();
ctx
->
run
();
}
}
}
...
...
libcaf_core/test/flow/merge.cpp
View file @
5477e042
...
...
@@ -52,6 +52,8 @@ SCENARIO("mergers round-robin over their inputs") {
ctx
->
run
();
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
subscribed
);
CHECK
(
snk
->
buf
.
empty
());
uut
->
dispose
();
ctx
->
run
();
}
}
}
...
...
libcaf_core/test/flow/never.cpp
View file @
5477e042
...
...
@@ -22,10 +22,10 @@ struct fixture : test_coordinator_fixture<> {
BEGIN_FIXTURE_SCOPE
(
fixture
)
SCENARIO
(
"a mute observable never invokes any callbacks"
)
{
GIVEN
(
"a
n
never<int32>"
)
{
SCENARIO
(
"a mute observable never invokes any callbacks
except when disposed
"
)
{
GIVEN
(
"a never<int32>"
)
{
WHEN
(
"an observer subscribes"
)
{
THEN
(
"the observer never
observes any activity
"
)
{
THEN
(
"the observer never
receives any events
"
)
{
auto
uut
=
ctx
->
make_observable
().
never
<
int32_t
>
();
auto
snk
=
flow
::
make_passive_observer
<
int32_t
>
();
uut
.
subscribe
(
snk
->
as_observer
());
...
...
@@ -39,6 +39,28 @@ SCENARIO("a mute observable never invokes any callbacks") {
}
}
}
GIVEN
(
"a never<int32> that gets disposed"
)
{
WHEN
(
"an observer subscribes"
)
{
THEN
(
"the observer receives on_complete"
)
{
auto
uut
=
ctx
->
make_observable
().
never
<
int32_t
>
();
auto
snk1
=
flow
::
make_passive_observer
<
int32_t
>
();
auto
snk2
=
flow
::
make_passive_observer
<
int32_t
>
();
uut
.
subscribe
(
snk1
->
as_observer
());
ctx
->
run
();
if
(
CHECK
(
snk1
->
sub
))
{
snk1
->
sub
.
request
(
42
);
ctx
->
run
();
CHECK_EQ
(
snk1
->
state
,
flow
::
observer_state
::
subscribed
);
CHECK
(
snk1
->
buf
.
empty
());
uut
.
dispose
();
ctx
->
run
();
CHECK_EQ
(
snk1
->
state
,
flow
::
observer_state
::
completed
);
uut
.
subscribe
(
snk2
->
as_observer
());
CHECK_EQ
(
snk2
->
state
,
flow
::
observer_state
::
aborted
);
}
}
}
}
}
END_FIXTURE_SCOPE
()
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