85.11% Lines (40/47) 75.00% Functions (12/16)
TLA Baseline Branch
Line Hits Code Line Hits Code
  1 + //
  2 + // Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
  3 + //
  4 + // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5 + // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6 + //
  7 + // Official repository: https://github.com/cppalliance/capy
  8 + //
  9 +
  10 + #ifndef BOOST_CAPY_ASIO_CONTINUATION_HPP
  11 + #define BOOST_CAPY_ASIO_CONTINUATION_HPP
  12 +
  13 + #include <boost/capy/continuation.hpp>
  14 + #include <boost/capy/concept/executor.hpp>
  15 +
  16 + #include <memory>
  17 +
  18 + namespace boost::capy
  19 + {
  20 +
  21 + namespace detail
  22 + {
  23 +
  24 + template<typename Allocator>
  25 + struct continuation_handle_promise_base_
  26 + {
  27 + using alloc_t = std::allocator_traits<Allocator>
  28 + ::template rebind_alloc<char>;
  29 +
  30 + template<typename Func>
HITGNC   31 + 5 void * operator new(std::size_t n, Func &, Allocator &allocator_)
  32 + {
HITGNC   33 + 5 alloc_t alloc(allocator_);
HITGNC   34 + 5 std::size_t m = n;
HITGNC   35 + 5 if (n % alignof(alloc_t) > 0)
MISUNC   36 + m += alignof(alloc_t) - (n % alignof(alloc_t));
  37 +
HITGNC   38 + 5 char * mem = alloc.allocate(m + sizeof(alloc));
  39 +
HITGNC   40 + 5 new (mem + m) alloc_t(std::move(alloc));
HITGNC   41 + 5 return mem;
  42 + }
  43 +
HITGNC   44 + 5 void operator delete(void * p, std::size_t n)
  45 + {
HITGNC   46 + 5 std::size_t m = n;
HITGNC   47 + 5 if (n % alignof(alloc_t) > 0)
MISUNC   48 + m += alignof(alloc_t) - (n % alignof(alloc_t));
  49 +
HITGNC   50 + 5 auto * a = reinterpret_cast<alloc_t*>(static_cast<char*>(p) + m);
  51 +
HITGNC   52 + 5 alloc_t alloc(std::move(*a));
HITGNC   53 + 5 a->~alloc_t();
  54 +
HITGNC   55 + 5 alloc.deallocate(static_cast<char*>(p), n);
HITGNC   56 + 5 }
  57 + };
  58 +
  59 +
  60 + template<>
  61 + struct continuation_handle_promise_base_<std::allocator<void>>
  62 + {
  63 + };
  64 +
  65 + template<typename Allocator>
  66 + struct continuation_handle_promise_type
  67 + : continuation_handle_promise_base_<Allocator>
  68 + {
  69 +
  70 + struct initial_aw_t
  71 + {
HITGNC   72 + 11 bool await_ready() const {return false;}
HITGNC   73 + 11 void await_suspend(
  74 + std::coroutine_handle<continuation_handle_promise_type<Allocator>> h)
  75 + {
HITGNC   76 + 11 auto & c = h.promise().cont;
HITGNC   77 + 11 c.h = h;
HITGNC   78 + 11 c.next = nullptr;
HITGNC   79 + 11 }
HITGNC   80 + 11 void await_resume() {}
  81 + };
  82 +
HITGNC   83 + 11 initial_aw_t initial_suspend() const noexcept
  84 + {
HITGNC   85 + 11 return initial_aw_t{};
  86 + }
MISUNC   87 + std::suspend_never final_suspend() const noexcept {return {};}
  88 +
  89 + template<typename Function>
HITGNC   90 + 11 auto yield_value(Function & func)
  91 + {
  92 + struct yielder
  93 + {
  94 + Function func;
  95 +
HITGNC   96 + 11 bool await_ready() const {return false;}
HITGNC   97 + 11 void await_suspend(std::coroutine_handle<> h)
  98 + {
HITGNC   99 + 11 auto f = std::move(func);
HITGNC   100 + 11 h.destroy();
  101 +
  102 + #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 14)
  103 + #pragma GCC diagnostic push
  104 + #pragma GCC diagnostic ignored "-Warray-bounds"
  105 + #endif
  106 +
HITGNC   107 + 11 std::move(f)();
  108 +
  109 + #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 14)
  110 + #pragma GCC diagnostic pop
  111 + #endif
  112 +
HITGNC   113 + 11 }
MISUNC   114 + void await_resume() {}
  115 + };
  116 +
HITGNC   117 + 11 return yielder{std::move(func)};
  118 + }
  119 +
MISUNC   120 + void unhandled_exception() { throw; }
MISUNC   121 + void return_void() {}
  122 +
  123 + continuation cont;
  124 +
  125 + struct helper
  126 + {
  127 + continuation * cont;
  128 + using promise_type = continuation_handle_promise_type;
  129 + };
  130 +
HITGNC   131 + 11 helper get_return_object()
  132 + {
HITGNC   133 + 11 return helper{&cont};
  134 + }
  135 + };
  136 +
  137 + #if defined(__GNUC__) && !defined(__clang__)
  138 + #pragma GCC diagnostic push
  139 + #pragma GCC diagnostic ignored "-Wmismatched-new-delete"
  140 + #endif
  141 +
  142 + template<std::invocable<> Function, typename Allocator>
HITGNC   143 + 11 auto make_continuation_helper(
  144 + Function func,
  145 + Allocator)
  146 + -> continuation_handle_promise_type<Allocator>::helper
  147 + {
  148 + co_yield func;
HITGNC   149 + 22 }
  150 +
  151 + #if defined(__GNUC__) && !defined(__clang__)
  152 + #pragma GCC diagnostic pop
  153 + #endif
  154 +
  155 + template<std::invocable<> Function, typename Allocator>
HITGNC   156 + 11 continuation & make_continuation(
  157 + Function && func,
  158 + Allocator && alloc)
  159 + {
HITGNC   160 + 11 continuation * c = detail::make_continuation_helper(
MISUNC   161 + std::forward<Function>(func),
HITGNC   162 + 11 std::forward<Allocator>(alloc)).cont;
HITGNC   163 + 11 return *c;
  164 + }
  165 +
  166 + }
  167 +
  168 +
  169 + }
  170 +
  171 + #endif
  172 +