Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/external/callback_awaitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ template <typename Awaitable> struct callback_awaitable_impl {
tmc::detail::result_storage_t<typename Awaitable::ResultTuple> result;

friend Awaitable;
callback_awaitable_impl(Awaitable& Handle) : handle(Handle) {}
callback_awaitable_impl(Awaitable& Handle TMC_LIFETIMEBOUND) : handle(Handle) {}

bool await_ready() { return false; }

Expand Down Expand Up @@ -121,7 +121,7 @@ template <typename... ResultArgs> struct wrapper {
);
}

callback_awaitable_impl<callback_awaitable> operator co_await() {
callback_awaitable_impl<callback_awaitable> operator co_await() TMC_LIFETIMEBOUND {
return callback_awaitable_impl<callback_awaitable>(*this);
}
};
Expand Down Expand Up @@ -166,7 +166,7 @@ template <IsAwCallback Awaitable> struct awaitable_traits<Awaitable> {
using self_type = Awaitable;

// Values controlling the behavior when awaited directly in a tmc::task
static decltype(auto) get_awaiter(self_type&& awaitable) {
static decltype(auto) get_awaiter(self_type&& awaitable TMC_LIFETIMEBOUND) {
return std::forward<self_type>(awaitable).operator co_await();
}

Expand Down
2 changes: 1 addition & 1 deletion examples/external/external_awaitable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ template <typename Result> class external_awaitable {
});
}

Result& await_resume() & noexcept { return result; }
Result& await_resume() & noexcept TMC_LIFETIMEBOUND { return result; }
Result&& await_resume() && noexcept { return std::move(result); }

~external_awaitable() {
Expand Down
13 changes: 12 additions & 1 deletion examples/external/external_coro.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
#include <exception>
#include <utility>

// This example type deliberately has no knowledge of TMC, so it defines its
// own equivalent of TMC_LIFETIMEBOUND rather than using tmc/detail/compat.hpp.
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(clang::lifetimebound)
#define EXTERNAL_CORO_LIFETIMEBOUND [[clang::lifetimebound]]
#endif
#endif
#ifndef EXTERNAL_CORO_LIFETIMEBOUND
#define EXTERNAL_CORO_LIFETIMEBOUND
#endif

// A simple "external" awaitable coroutine type that has no knowledge of TMC.
template <typename Result> class aw_external_coro;
template <typename Result> struct external_coro_promise;
Expand Down Expand Up @@ -80,7 +91,7 @@ template <typename Result> class aw_external_coro {
p.result_ptr = &result;
return handle;
}
inline Result& await_resume() & noexcept {
inline Result& await_resume() & noexcept EXTERNAL_CORO_LIFETIMEBOUND {
handle.destroy();
return result;
}
Expand Down
4 changes: 2 additions & 2 deletions examples/external/external_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class tmc_external_executor {
/// This object shares a lifetime with this executor, and can be used for
/// pointer-based equality comparison against
/// the thread-local `tmc::current_executor()`.
tmc::ex_any* type_erased() { return &type_erased_this; }
tmc::ex_any* type_erased() TMC_LIFETIMEBOUND { return &type_erased_this; }
};

// A complete, minimal implementation of executor_traits.
Expand All @@ -105,7 +105,7 @@ template <> struct tmc::detail::executor_traits<tmc_external_executor> {
Ex.post_bulk(std::forward<It>(Items), Count, Priority, ThreadHint);
}

static inline tmc::ex_any* type_erased(tmc_external_executor& Ex) {
static inline tmc::ex_any* type_erased(tmc_external_executor& Ex TMC_LIFETIMEBOUND) {
return Ex.type_erased();
}

Expand Down
4 changes: 2 additions & 2 deletions examples/pipeline_fifo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ template <class F> class with_result_of_t {

public:
using T = decltype(std::declval<F&&>()());
explicit with_result_of_t(F&& f) : fun(std::forward<F>(f)) {}
explicit with_result_of_t(F&& f TMC_LIFETIMEBOUND) : fun(std::forward<F>(f)) {}
operator T() noexcept { return fun(); }
};

template <class F> inline with_result_of_t<F> with_result_of(F&& f) {
template <class F> inline with_result_of_t<F> with_result_of(F&& f TMC_LIFETIMEBOUND) {
return with_result_of_t<F>(std::forward<F>(f));
}

Expand Down
6 changes: 4 additions & 2 deletions tests/atomic_awaitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ template <typename T> struct atomic_awaitable : private AtomicAwaitableTag {
}

std::atomic<T>& ref() { return value; }
operator std::atomic<T>&() { return value; }
operator std::atomic<T>&() TMC_LIFETIMEBOUND { return value; }
T load() { return value.load(); }

void async_initiate() {
Expand Down Expand Up @@ -84,7 +84,9 @@ template <IsAwAtomic Awaitable> struct awaitable_traits<Awaitable> {
using self_type = Awaitable;

// Values controlling the behavior when awaited directly in a tmc::task
static decltype(auto) get_awaiter(self_type& awaitable) noexcept { return awaitable; }
static decltype(auto) get_awaiter(self_type& awaitable TMC_LIFETIMEBOUND) noexcept {
return awaitable;
}

// Values controlling the behavior when wrapped by a utility function
// such as tmc::spawn_*()
Expand Down
7 changes: 5 additions & 2 deletions tests/test_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ struct move_counter {
int value;
std::atomic<size_t>* count;

move_counter(int v, std::atomic<size_t>* c) noexcept : value(v), count(c) {}
move_counter(int v, std::atomic<size_t>* c TMC_LIFETIMEBOUND) noexcept
: value(v), count(c) {}

move_counter(move_counter&& Other) noexcept : value(Other.value), count(Other.count) {
Other.count = nullptr;
Expand Down Expand Up @@ -541,7 +542,9 @@ struct immovable_destructor_counter {
size_t value;
std::atomic<size_t>* count;

immovable_destructor_counter(size_t v, std::atomic<size_t>* c) noexcept
immovable_destructor_counter(
size_t v, std::atomic<size_t>* c TMC_LIFETIMEBOUND
) noexcept
: value(v), count(c) {}

~immovable_destructor_counter() { ++(*count); }
Expand Down
10 changes: 10 additions & 0 deletions tests/test_chase_lev_deque.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,12 @@ TEST_F(CATEGORY, concurrent_owner_and_stealers) {
stealers.reserve(NUM_STEALERS);
for (size_t s = 0; s < NUM_STEALERS; ++s) {
stealers.emplace_back([&, s]() {
// The invalidation warning is a false positive: push_back on the inner
// vector cannot invalidate `out`, which refers to the inner vector
// object itself (not to its elements).
TMC_DISABLE_WARNING_LIFETIME_INVALIDATION_BEGIN
auto& out = stolen[static_cast<size_t>(s)];
TMC_DISABLE_WARNING_LIFETIME_INVALIDATION_END
out.reserve(N / NUM_STEALERS);
size_t v = 0;
while (true) {
Expand Down Expand Up @@ -446,7 +451,12 @@ TEST_F(CATEGORY, concurrent_post_bulk_with_stealers) {
stealers.reserve(NUM_STEALERS);
for (size_t s = 0; s < NUM_STEALERS; ++s) {
stealers.emplace_back([&, s]() {
// The invalidation warning is a false positive: push_back on the inner
// vector cannot invalidate `out`, which refers to the inner vector
// object itself (not to its elements).
TMC_DISABLE_WARNING_LIFETIME_INVALIDATION_BEGIN
auto& out = stolen[static_cast<size_t>(s)];
TMC_DISABLE_WARNING_LIFETIME_INVALIDATION_END
size_t v = 0;
while (true) {
if (q.steal(v)) {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ template <typename Arr> tmc::task<size_t> inc_task_int(Arr& arr, size_t idx) {

struct destructor_counter {
std::atomic<size_t>* count;
destructor_counter(std::atomic<size_t>* C) noexcept : count{C} {}
destructor_counter(std::atomic<size_t>* C TMC_LIFETIMEBOUND) noexcept : count{C} {}
destructor_counter(destructor_counter const& Other) = delete;
destructor_counter& operator=(destructor_counter const& Other) = delete;

Expand Down
2 changes: 1 addition & 1 deletion tests/test_coro_functor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ TEST_F(CATEGORY, lambda) {
struct inv {
int* r;
int* d;
inv(int& R, int& D) : r(&R), d(&D) {}
inv(int& R TMC_LIFETIMEBOUND, int& D TMC_LIFETIMEBOUND) : r(&R), d(&D) {}
void operator()() {
EXPECT_NE(r, nullptr);
*r = 1;
Expand Down
6 changes: 4 additions & 2 deletions tests/test_exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ TEST_F(CATEGORY, wrapper_throw_move_only_unknown) {
template <bool Known>
struct aw_throw_on_other_executor_void : public KnownTag<Known> {
tmc::ex_braid& other_ex;
aw_throw_on_other_executor_void(tmc::ex_braid& OtherEx) : other_ex{OtherEx} {}
aw_throw_on_other_executor_void(tmc::ex_braid& OtherEx TMC_LIFETIMEBOUND)
: other_ex{OtherEx} {}
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> Outer) {
tmc::detail::post_checked(other_ex.type_erased(), std::move(Outer));
Expand All @@ -412,7 +413,8 @@ struct aw_throw_on_other_executor_void : public KnownTag<Known> {
template <bool Known>
struct aw_throw_on_other_executor_int : public KnownTag<Known> {
tmc::ex_braid& other_ex;
aw_throw_on_other_executor_int(tmc::ex_braid& OtherEx) : other_ex{OtherEx} {}
aw_throw_on_other_executor_int(tmc::ex_braid& OtherEx TMC_LIFETIMEBOUND)
: other_ex{OtherEx} {}
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> Outer) {
tmc::detail::post_checked(other_ex.type_erased(), std::move(Outer));
Expand Down
2 changes: 1 addition & 1 deletion tests/test_mux_many.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ TEST_F(CATEGORY, mux_many_eager_async_initiate_unknown_sized_iterator) {
int i;
using value_type = mux_immediate_async_op;
value_type operator*() const { return mux_immediate_async_op(1 << i); }
op_iter& operator++() {
op_iter& operator++() TMC_LIFETIMEBOUND {
++i;
return *this;
}
Expand Down
6 changes: 4 additions & 2 deletions tests/test_mux_tuple_zerocopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ struct zc_config : tmc::qu_mpsc_unbounded_default_config {
struct counted {
std::atomic<size_t>* count;
size_t value;
counted(std::atomic<size_t>* C, size_t V) noexcept : count{C}, value{V} {}
counted(std::atomic<size_t>* C TMC_LIFETIMEBOUND, size_t V) noexcept
: count{C}, value{V} {}
counted(counted const&) = delete;
counted& operator=(counted const&) = delete;
~counted() {
Expand All @@ -85,7 +86,8 @@ struct no_default_counted {
std::atomic<size_t>* count;
size_t value;
no_default_counted() = delete;
no_default_counted(std::atomic<size_t>* C, size_t V) noexcept : count{C}, value{V} {}
no_default_counted(std::atomic<size_t>* C TMC_LIFETIMEBOUND, size_t V) noexcept
: count{C}, value{V} {}
no_default_counted(no_default_counted const&) = delete;
no_default_counted& operator=(no_default_counted const&) = delete;
no_default_counted(no_default_counted&& Other) noexcept
Expand Down
2 changes: 1 addition & 1 deletion tests/test_qu_mpsc_unbounded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ template <size_t Pack> struct q_config : tmc::qu_mpsc_unbounded_default_config {
struct mpsc_destructor_counter {
std::atomic<size_t>* count;
[[maybe_unused]] mpsc_destructor_counter() noexcept : count{nullptr} {}
mpsc_destructor_counter(std::atomic<size_t>* C) noexcept : count{C} {}
mpsc_destructor_counter(std::atomic<size_t>* C TMC_LIFETIMEBOUND) noexcept : count{C} {}
mpsc_destructor_counter(mpsc_destructor_counter const& Other) = delete;
mpsc_destructor_counter& operator=(mpsc_destructor_counter const& Other) = delete;

Expand Down
2 changes: 1 addition & 1 deletion tests/test_qu_spsc_bounded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ template <size_t Pack> struct qu_config : tmc::qu_spsc_bounded_default_config {
struct spsc_destructor_counter {
std::atomic<size_t>* count;
[[maybe_unused]] spsc_destructor_counter() noexcept : count{nullptr} {}
spsc_destructor_counter(std::atomic<size_t>* C) noexcept : count{C} {}
spsc_destructor_counter(std::atomic<size_t>* C TMC_LIFETIMEBOUND) noexcept : count{C} {}
spsc_destructor_counter(spsc_destructor_counter const& Other) = delete;
spsc_destructor_counter& operator=(spsc_destructor_counter const& Other) = delete;

Expand Down
2 changes: 1 addition & 1 deletion tests/test_qu_spsc_unbounded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ template <size_t Pack> struct qu_config : tmc::qu_spsc_unbounded_default_config
struct spsc_destructor_counter {
std::atomic<size_t>* count;
[[maybe_unused]] spsc_destructor_counter() noexcept : count{nullptr} {}
spsc_destructor_counter(std::atomic<size_t>* C) noexcept : count{C} {}
spsc_destructor_counter(std::atomic<size_t>* C TMC_LIFETIMEBOUND) noexcept : count{C} {}
spsc_destructor_counter(spsc_destructor_counter const& Other) = delete;
spsc_destructor_counter& operator=(spsc_destructor_counter const& Other) = delete;

Expand Down
2 changes: 1 addition & 1 deletion tests/test_spawn_composition.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ static inline tmc::task<void> spawn_many_compose_spawn_func_many() {
return tmc::spawn_func_many<2>(
(
std::ranges::views::iota(void_results.data() + (i * 2)) |
std::ranges::views::transform([](int* j) -> auto {
std::ranges::views::transform([](int* j TMC_LIFETIMEBOUND) -> auto {
return [j]() { *j = (1 << *j); };
})
).begin()
Expand Down
Loading