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
7d702528
Commit
7d702528
authored
May 09, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix copy-constructors of async::promise
parent
f30ebfdd
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
90 additions
and
9 deletions
+90
-9
libcaf_core/caf/action.hpp
libcaf_core/caf/action.hpp
+12
-2
libcaf_core/caf/async/future.hpp
libcaf_core/caf/async/future.hpp
+11
-1
libcaf_core/caf/async/promise.hpp
libcaf_core/caf/async/promise.hpp
+15
-6
libcaf_core/test/async/promise.cpp
libcaf_core/test/async/promise.cpp
+52
-0
No files found.
libcaf_core/caf/action.hpp
View file @
7d702528
...
...
@@ -121,7 +121,7 @@ private:
}
// namespace caf
namespace
caf
::
detail
{
template
<
class
F
>
template
<
class
F
,
bool
IsSingleShot
>
struct
default_action_impl
:
detail
::
atomic_ref_counted
,
action
::
impl
{
std
::
atomic
<
action
::
state
>
state_
;
F
f_
;
...
...
@@ -149,6 +149,8 @@ struct default_action_impl : detail::atomic_ref_counted, action::impl {
// to implement time-based loops.
if
(
state_
.
load
()
==
action
::
state
::
scheduled
)
{
f_
();
if
constexpr
(
IsSingleShot
)
state_
=
action
::
state
::
disposed
;
}
}
...
...
@@ -177,7 +179,15 @@ namespace caf {
/// @param f The body for the action.
template
<
class
F
>
action
make_action
(
F
f
)
{
using
impl_t
=
detail
::
default_action_impl
<
F
>
;
using
impl_t
=
detail
::
default_action_impl
<
F
,
false
>
;
return
action
{
make_counted
<
impl_t
>
(
std
::
move
(
f
))};
}
/// Convenience function for creating an @ref action from a function object.
/// @param f The body for the action.
template
<
class
F
>
action
make_single_shot_action
(
F
f
)
{
using
impl_t
=
detail
::
default_action_impl
<
F
,
true
>
;
return
action
{
make_counted
<
impl_t
>
(
std
::
move
(
f
))};
}
...
...
libcaf_core/caf/async/future.hpp
View file @
7d702528
...
...
@@ -47,7 +47,7 @@ public:
g
(
static_cast
<
const
error
&>
(
std
::
get
<
error
>
(
cp
->
value
)));
}
};
auto
cb_action
=
make_action
(
std
::
move
(
cb
));
auto
cb_action
=
make_
single_shot_
action
(
std
::
move
(
cb
));
auto
event
=
typename
cell_type
::
event
{
ctx_
,
cb_action
};
bool
fire_immediately
=
false
;
{
// Critical section.
...
...
@@ -115,6 +115,16 @@ public:
return
{
ctx
,
cell_
};
}
/// Queries whether the result of the asynchronous computation is still
/// pending, i.e., neither `set_value` nor `set_error` has been called on the
/// @ref promise.
/// @pre `valid()`
bool
pending
()
const
{
CAF_ASSERT
(
valid
());
std
::
unique_lock
guard
{
cell_
->
mtx
};
return
std
::
holds_alternative
<
none_t
>
(
cell_
->
value
);
}
private:
using
cell_ptr
=
std
::
shared_ptr
<
detail
::
async_cell
<
T
>>
;
...
...
libcaf_core/caf/async/promise.hpp
View file @
7d702528
...
...
@@ -19,16 +19,25 @@ template <class T>
class
promise
{
public:
promise
(
promise
&&
)
noexcept
=
default
;
promise
(
const
promise
&
)
noexcept
=
default
;
promise
&
operator
=
(
promise
&&
)
noexcept
=
default
;
promise
&
operator
=
(
const
promise
&
)
noexcept
=
default
;
promise
(
const
promise
&
other
)
noexcept
:
promise
(
other
.
cell_
)
{
// nop
}
promise
&
operator
=
(
const
promise
&
other
)
noexcept
{
promise
copy
{
other
};
cell_
.
swap
(
copy
.
cell_
);
return
*
this
;
}
promise
()
:
cell_
(
std
::
make_shared
<
cell_type
>
())
{
// nop
}
~
promise
()
{
if
(
cell_
)
{
if
(
valid
()
)
{
auto
&
cnt
=
cell_
->
promises
;
if
(
cnt
==
1
||
cnt
.
fetch_sub
(
1
,
std
::
memory_order_acq_rel
)
==
1
)
{
typename
cell_type
::
event_list
events
;
...
...
@@ -59,7 +68,7 @@ public:
/// @pre `valid()`
void
set_value
(
T
value
)
{
if
(
cell_
)
{
if
(
valid
()
)
{
do_set
(
value
);
cell_
=
nullptr
;
}
...
...
@@ -67,7 +76,7 @@ public:
/// @pre `valid()`
void
set_error
(
error
reason
)
{
if
(
cell_
)
{
if
(
valid
()
)
{
do_set
(
reason
);
cell_
=
nullptr
;
}
...
...
@@ -82,7 +91,7 @@ private:
using
cell_type
=
detail
::
async_cell
<
T
>
;
using
cell_ptr
=
std
::
shared_ptr
<
cell_type
>
;
explicit
promise
(
cell_
type
cell
)
:
cell_
(
std
::
move
(
cell
))
{
explicit
promise
(
cell_
ptr
cell
)
noexcept
:
cell_
(
std
::
move
(
cell
))
{
CAF_ASSERT
(
cell_
!=
nullptr
);
cell_
->
promises
.
fetch_add
(
1
,
std
::
memory_order_relaxed
);
}
...
...
libcaf_core/test/async/promise.cpp
View file @
7d702528
...
...
@@ -8,6 +8,7 @@
#include "core-test.hpp"
#include "caf/flow/scoped_coordinator.hpp"
#include "caf/scheduled_actor/flow.hpp"
using
namespace
caf
;
...
...
@@ -71,4 +72,55 @@ SCENARIO("actors can observe futures") {
}
}
SCENARIO
(
"never setting a value or an error breaks the promises"
)
{
GIVEN
(
"multiple promises that point to the same cell"
)
{
WHEN
(
"the last promise goes out of scope"
)
{
THEN
(
"the future reports a broken promise"
)
{
using
promise_t
=
async
::
promise
<
int32_t
>
;
using
future_t
=
async
::
future
<
int32_t
>
;
future_t
fut
;
{
auto
uut
=
promise_t
{};
fut
=
uut
.
get_future
();
CHECK
(
fut
.
pending
());
{
// copy ctor
promise_t
cpy
{
uut
};
CHECK
(
fut
.
pending
());
// move ctor
promise_t
mv
{
std
::
move
(
cpy
)};
CHECK
(
fut
.
pending
());
{
// copy assign
promise_t
cpy2
;
cpy2
=
mv
;
CHECK
(
fut
.
pending
());
// move assign
promise_t
mv2
;
mv2
=
std
::
move
(
mv
);
CHECK
(
fut
.
pending
());
}
CHECK
(
fut
.
pending
());
}
CHECK
(
fut
.
pending
());
}
CHECK
(
!
fut
.
pending
());
auto
ctx
=
flow
::
scoped_coordinator
::
make
();
size_t
observed_events
=
0
;
fut
.
bind_to
(
ctx
.
get
()).
then
(
[
&
observed_events
](
int32_t
)
{
++
observed_events
;
FAIL
(
"unexpected value"
);
},
[
&
observed_events
](
const
error
&
err
)
{
++
observed_events
;
CHECK_EQ
(
err
,
make_error
(
sec
::
broken_promise
));
});
ctx
->
run
();
CHECK_EQ
(
observed_events
,
1u
);
}
}
}
}
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