2
0
mirror of https://github.com/boostorg/cobalt.git synced 2026-01-19 04:02:16 +00:00

added noop utility

closes #3
This commit is contained in:
Klemens Morgenstern
2024-05-01 20:12:44 +08:00
committed by Klemens Morgenstern
parent 34e22ee239
commit 6eafc81a87
10 changed files with 88 additions and 2 deletions

View File

@@ -15,6 +15,7 @@
#include <boost/cobalt/detail/this_thread.hpp>
#include <boost/cobalt/unique_handle.hpp>
#include <boost/cobalt/detail/wrapper.hpp>
#include <boost/cobalt/noop.hpp>
#include <boost/asio/bind_allocator.hpp>
#include <boost/core/exchange.hpp>
@@ -92,6 +93,8 @@ struct generator_receiver : generator_receiver_base<Yield, Push>
bool ready() { return exception || result || done; }
generator_receiver(noop<Yield> n) : result(std::move(n.value)), done(true) {}
generator_receiver() = default;
generator_receiver(generator_receiver && lhs)
: generator_receiver_base<Yield, Push>{std::move(lhs.pushed_value)},

View File

@@ -12,6 +12,7 @@
#include <boost/cobalt/detail/forward_cancellation.hpp>
#include <boost/cobalt/detail/wrapper.hpp>
#include <boost/cobalt/detail/this_thread.hpp>
#include <boost/cobalt/noop.hpp>
#include <boost/cobalt/unique_handle.hpp>
#include <boost/asio/cancellation_signal.hpp>
@@ -65,6 +66,8 @@ struct promise_value_holder
result.emplace(ret);
static_cast<promise_receiver<T>*>(this)->set_done();
}
constexpr promise_value_holder() = default;
constexpr promise_value_holder(noop<T> value) noexcept(std::is_nothrow_move_constructible_v<T>) : result(std::move(value.value)) {}
};
@@ -79,6 +82,9 @@ struct promise_value_holder<void>
}
inline void return_void();
constexpr promise_value_holder() = default;
constexpr promise_value_holder(noop<void>) {}
};
@@ -113,6 +119,7 @@ struct promise_receiver : promise_value_holder<T>
}
promise_receiver() = default;
promise_receiver(noop<T> value) : promise_value_holder<T>(std::move(value)), done(true) {}
promise_receiver(promise_receiver && lhs) noexcept
: promise_value_holder<T>(std::move(lhs)),
exception(std::move(lhs.exception)), done(lhs.done), awaited_from(std::move(lhs.awaited_from)),

View File

@@ -12,6 +12,7 @@
#include <boost/cobalt/detail/forward_cancellation.hpp>
#include <boost/cobalt/detail/wrapper.hpp>
#include <boost/cobalt/detail/this_thread.hpp>
#include <boost/cobalt/noop.hpp>
#include <boost/asio/bind_allocator.hpp>
#include <boost/asio/cancellation_signal.hpp>
@@ -59,6 +60,9 @@ struct task_value_holder
result.emplace(ret);
static_cast<task_receiver<T>*>(this)->set_done();
}
constexpr task_value_holder() noexcept = default;
constexpr task_value_holder(noop<T> n) noexcept(std::is_nothrow_move_constructible_v<T>) : result(std::move(n.value)) {}
};
template<>
@@ -72,6 +76,9 @@ struct task_value_holder<void>
}
inline void return_void();
constexpr task_value_holder() noexcept = default;
constexpr task_value_holder(noop<void> n) noexcept {}
};
@@ -114,6 +121,7 @@ struct task_receiver : task_value_holder<T>
promise->signal.emit(ct);
}
task_receiver(noop<T> n) : task_value_holder<T>(std::move(n)), done(true) {}
task_receiver() = default;
task_receiver(task_receiver && lhs)
: task_value_holder<T>(std::move(lhs)),

View File

@@ -47,6 +47,7 @@ struct [[nodiscard]] generator
generator(const generator &) = delete;
generator& operator=(const generator &) = delete;
constexpr generator(noop<Yield> n) : receiver_(std::move(n)){}
private:
template<typename, typename>

View File

@@ -0,0 +1,55 @@
//
// Copyright (c) 2024 Klemens Morgenstern (klemens.morgenstern@gmx.net)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_COBALT_NOOP_HPP
#define BOOST_COBALT_NOOP_HPP
#include <type_traits>
#include <utility>
namespace boost::cobalt
{
// tag::outline[]
// This is a tag type allowing the creation of promises or generators without creating a coroutine.
template<typename T = void>
struct noop
{
template<typename ... Args>
constexpr noop(Args && ... args) noexcept(std::is_nothrow_constructible_v<T, Args&&...>)
: value(std::forward<Args>(args)...)
{
}
// end::outline[]
T value;
constexpr static bool await_ready() {return true;}
template<typename P>
constexpr static void await_suspend(std::coroutine_handle<P>) {}
constexpr T await_resume() {return std::move(value);}
// tag::outline[]
};
// end::outline[]
template<> struct noop<void>
{
constexpr static bool await_ready() {return true;}
template<typename P>
constexpr static void await_suspend(std::coroutine_handle<P>) {}
constexpr static void await_resume() {}
};
template<typename T> noop( T &&) -> noop<T>;
template<typename T> noop(const T & ) -> noop<T>;
noop() -> noop<void>;
}
#endif //BOOST_COBALT_NOOP_HPP

View File

@@ -41,6 +41,10 @@ struct [[nodiscard]] promise
// end::outline[]
/* tag::outline[]
// Create an already completed promimse
static promise
// Get the return value. If !ready() this function has undefined behaviour.
Return get();
end::outline[] */
@@ -60,6 +64,8 @@ struct [[nodiscard]] promise
if (attached_)
cancel();
}
constexpr promise(noop<Return> n) : receiver_(std::move(n)), attached_(false) {}
private:
template<typename>
friend struct detail::cobalt_promise;

View File

@@ -34,6 +34,8 @@ struct [[nodiscard]] task
using promise_type = detail::task_promise<Return>;
constexpr task(noop<Return> n) : receiver_(std::move(n)){}
private:
template<typename>
friend struct detail::task_promise;

View File

@@ -296,11 +296,14 @@ cobalt::generator<int, int> detached_push()
co_return i;
}
cobalt::generator<int> np() {return cobalt::noop(42);}
CO_TEST_CASE(detached_push_)
{
auto g = detached_push();
co_await g(1);
co_await np();
}
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(unwind)
cobalt::promise<int> return_(std::size_t ms)
{
co_return 1234u;
return cobalt::noop(1234);
}
cobalt::promise<int> return_(std::size_t ms, asio::executor_arg_t,

View File

@@ -34,11 +34,12 @@ namespace
cobalt::task<void> test0()
{
co_return;
return cobalt::noop<void>();
}
cobalt::task<double> test2(int i)
{
co_await cobalt::noop();
co_await test0();
co_return i;
}