Skip to content

Commit 9e4ab51

Browse files
fixed move assigns.
closes #159
1 parent 4f612b9 commit 9e4ab51

File tree

8 files changed

+117
-26
lines changed

8 files changed

+117
-26
lines changed

include/boost/cobalt/detail/generator.hpp

+32-7
Original file line numberDiff line numberDiff line change
@@ -104,26 +104,51 @@ struct generator_receiver : generator_receiver_base<Yield, Push>
104104
{
105105
if (!lhs.done && !lhs.exception)
106106
{
107-
reference = this;
107+
*reference = this;
108108
lhs.exception = moved_from_exception();
109109
}
110110
lhs.done = true;
111111
}
112112

113+
generator_receiver& operator=(generator_receiver && lhs) noexcept
114+
{
115+
if (!done && *reference == this)
116+
*reference = nullptr;
117+
118+
this->pushed_value = std::move(lhs.pushed_value);
119+
exception = std::move(std::move(lhs.exception));
120+
done = std::move(lhs.done);
121+
result = std::move(std::move(lhs.result));
122+
result_buffer = std::move(std::move(lhs.result_buffer));
123+
awaited_from = std::move(std::move(lhs.awaited_from));
124+
yield_from = std::move(std::move(lhs.yield_from));
125+
lazy = std::move(lhs.lazy);
126+
reference = lhs.reference;
127+
cancel_signal = std::move(lhs.cancel_signal);
128+
129+
if (!lhs.done && !lhs.exception && *reference == &lhs)
130+
{
131+
*reference = this;
132+
lhs.exception = moved_from_exception();
133+
}
134+
lhs.done = true;
135+
return *this;
136+
}
137+
113138
~generator_receiver()
114139
{
115-
if (!done && reference == this)
116-
reference = nullptr;
140+
if (!done && *reference == this)
141+
*reference = nullptr;
117142
}
118143

119144
generator_receiver(generator_receiver * &reference, asio::cancellation_signal & cancel_signal)
120-
: reference(reference), cancel_signal(cancel_signal)
145+
: reference(&reference), cancel_signal(&cancel_signal)
121146
{
122147
reference = this;
123148
}
124149

125-
generator_receiver * &reference;
126-
asio::cancellation_signal & cancel_signal;
150+
generator_receiver **reference;
151+
asio::cancellation_signal * cancel_signal;
127152

128153
using yield_awaitable = generator_yield_awaitable<Yield, Push>;
129154

@@ -185,7 +210,7 @@ struct generator_receiver : generator_receiver_base<Yield, Push>
185210

186211
if constexpr (requires (Promise p) {p.get_cancellation_slot();})
187212
if ((cl = h.promise().get_cancellation_slot()).is_connected())
188-
cl.emplace<forward_cancellation>(self->cancel_signal);
213+
cl.emplace<forward_cancellation>(*self->cancel_signal);
189214

190215
self->awaited_from.reset(h.address());
191216

include/boost/cobalt/detail/promise.hpp

+28-7
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,43 @@ struct promise_receiver : promise_value_holder<T>
120120
{
121121
if (!done && !exception)
122122
{
123-
reference = this;
123+
*reference = this;
124124
lhs.exception = moved_from_exception();
125125
}
126126

127127
lhs.done = true;
128+
}
129+
130+
promise_receiver& operator=(promise_receiver && lhs) noexcept
131+
{
132+
if (!done && *reference == this)
133+
*reference = nullptr;
128134

135+
promise_value_holder<T>::operator= (std::move(lhs));
136+
exception = std::move(lhs.exception);
137+
done = lhs.done;
138+
awaited_from = std::move(lhs.awaited_from);
139+
reference = lhs.reference;
140+
cancel_signal = lhs.cancel_signal;
141+
142+
if (!done && !exception && *reference == &lhs)
143+
{
144+
*reference = this;
145+
lhs.exception = moved_from_exception();
146+
}
147+
148+
lhs.done = true;
149+
return *this;
129150
}
130151

131152
~promise_receiver()
132153
{
133-
if (!done && reference == this)
134-
reference = nullptr;
154+
if (!done && *reference == this)
155+
*reference = nullptr;
135156
}
136157

137158
promise_receiver(promise_receiver * &reference, asio::cancellation_signal & cancel_signal)
138-
: reference(reference), cancel_signal(cancel_signal)
159+
: reference(&reference), cancel_signal(&cancel_signal)
139160
{
140161
reference = this;
141162
}
@@ -176,7 +197,7 @@ struct promise_receiver : promise_value_holder<T>
176197

177198
if constexpr (requires (Promise p) {p.get_cancellation_slot();})
178199
if ((cl = h.promise().get_cancellation_slot()).is_connected())
179-
cl.emplace<forward_cancellation>(self->cancel_signal);
200+
cl.emplace<forward_cancellation>(*self->cancel_signal);
180201

181202
self->awaited_from.reset(h.address());
182203
return true;
@@ -232,8 +253,8 @@ struct promise_receiver : promise_value_holder<T>
232253
}
233254
};
234255

235-
promise_receiver * &reference;
236-
asio::cancellation_signal & cancel_signal;
256+
promise_receiver ** reference;
257+
asio::cancellation_signal * cancel_signal;
237258

238259
awaitable get_awaitable() {return awaitable{this};}
239260

include/boost/cobalt/detail/task.hpp

+29-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ struct task_receiver : task_value_holder<T>
109109
}
110110

111111
task_receiver() = default;
112-
task_receiver(task_receiver && lhs)
112+
task_receiver(task_receiver && lhs) noexcept
113113
: task_value_holder<T>(std::move(lhs)),
114114
exception(std::move(lhs.exception)), done(lhs.done), awaited_from(std::move(lhs.awaited_from)),
115115
promise(lhs.promise)
@@ -123,6 +123,34 @@ struct task_receiver : task_value_holder<T>
123123
lhs.done = true;
124124
}
125125

126+
task_receiver& operator=(task_receiver && lhs) noexcept
127+
{
128+
if (!done && promise && promise->receiver == this)
129+
{
130+
promise->receiver = nullptr;
131+
if (!promise->started)
132+
std::coroutine_handle<task_promise<T>>::from_promise(*promise).destroy();
133+
}
134+
135+
task_value_holder<T>::operator=(std::move(lhs));
136+
137+
exception = std::move(lhs.exception);
138+
done = lhs.done;
139+
awaited_from = std::move(lhs.awaited_from);
140+
promise = lhs.promise;
141+
142+
143+
if (!done && !exception)
144+
{
145+
promise->receiver = this;
146+
lhs.exception = moved_from_exception();
147+
}
148+
149+
lhs.done = true;
150+
return *this;
151+
}
152+
153+
126154
~task_receiver()
127155
{
128156
if (!done && promise && promise->receiver == this)

include/boost/cobalt/generator.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ inline generator<Yield, Push>::operator bool() const
8989
template<typename Yield, typename Push >
9090
inline void generator<Yield, Push>::cancel(asio::cancellation_type ct)
9191
{
92-
if (!receiver_.done && receiver_.reference == &receiver_)
93-
receiver_.cancel_signal.emit(ct);
92+
if (!receiver_.done && *receiver_.reference == &receiver_)
93+
receiver_.cancel_signal->emit(ct);
9494
}
9595

9696
template<typename Yield, typename Push >

include/boost/cobalt/promise.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ promise<T>& promise<T>::operator=(promise && lhs) noexcept
9191
cancel();
9292
receiver_ = std::move(lhs.receiver_);
9393
attached_ = std::exchange(lhs.attached_, false);
94+
95+
return *this;
9496
}
9597

9698
template<typename T>
@@ -106,8 +108,8 @@ template<typename T>
106108
inline
107109
void promise<T>::cancel(asio::cancellation_type ct)
108110
{
109-
if (!receiver_.done && receiver_.reference == &receiver_)
110-
receiver_.cancel_signal.emit(ct);
111+
if (!receiver_.done && *receiver_.reference == &receiver_)
112+
receiver_.cancel_signal->emit(ct);
111113
}
112114

113115
template<typename T>

test/generator.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ CO_TEST_CASE(generator_int)
4343
while (g)
4444
BOOST_CHECK(i ++ == co_await g);
4545

46-
47-
4846
BOOST_CHECK(i == 11);
4947

48+
g = gen();
49+
5050
co_return ;
5151
}
5252

test/promise.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ cobalt::promise<double> test2(int i)
3434

3535
cobalt::promise<int> test1(asio::any_io_executor exec)
3636
{
37-
co_await test2(42);
38-
co_await test2(42);
37+
auto t1 = test2(42);
38+
co_await t1;
39+
t1 = test2(42);
40+
co_await t1;
3941

4042
BOOST_CHECK(test2(42).get() == 42);
4143

@@ -85,7 +87,7 @@ cobalt::promise<std::size_t> delay_r(asio::io_context &ctx, std::size_t ms,
8587

8688
cobalt::promise<std::size_t> delay_r(asio::any_io_executor exec, std::size_t ms)
8789
{
88-
auto tim = cobalt::use_op.as_default_on(asio::steady_timer(exec, std::chrono::milliseconds{ms}));
90+
auto tim = cobalt::use_op.as_default_on(asio::steady_timer(exec, std::chrono::milliseconds{ms}));
8991
co_await tim.async_wait();
9092
co_return ms;
9193
}
@@ -159,4 +161,5 @@ CO_TEST_CASE(move_only)
159161
co_await pro_move_only_test();
160162
}
161163

164+
162165
BOOST_AUTO_TEST_SUITE_END();

test/task.cpp

+14-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <boost/core/ignore_unused.hpp>
2525

2626
#include <new>
27+
#include <deque>
2728

2829
using namespace boost;
2930

@@ -45,8 +46,10 @@ cobalt::task<double> test2(int i)
4546

4647
cobalt::task<int> test1()
4748
{
48-
co_await test2(42);
49-
co_await test2(42);
49+
auto t = test2(42);
50+
co_await t;
51+
t = test2(42);
52+
co_await t;
5053

5154

5255
co_await asio::post(co_await cobalt::this_coro::executor, cobalt::use_task);
@@ -312,5 +315,14 @@ CO_TEST_CASE(move_only)
312315
co_await task_move_only_test();
313316
}
314317

318+
static_assert(std::is_move_assignable_v<cobalt::task<void>>);
319+
static_assert(std::is_move_assignable_v<cobalt::task<int>>);
320+
static_assert(std::is_move_constructible_v<cobalt::task<void>>);
321+
static_assert(std::is_move_constructible_v<cobalt::task<int>>);
322+
323+
void foo(std::deque<boost::cobalt::task<void>> & session_promisses)
324+
{
325+
session_promisses.erase(session_promisses.begin() + 1234);
326+
}
315327

316328
BOOST_AUTO_TEST_SUITE_END();

0 commit comments

Comments
 (0)