Skip to content
Draft
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
37 changes: 37 additions & 0 deletions include/boost/capy/asio/detail/asio_context_service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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)
//
// Official repository: https://github.com/cppalliance/capy
//

#ifndef BOOST_CAPY_ASIO_DETAIL_ASIO_CONTEXT_SERVICE
#define BOOST_CAPY_ASIO_DETAIL_ASIO_CONTEXT_SERVICE

#include <boost/capy/ex/execution_context.hpp>

namespace boost::capy::detail
{

template<typename Context>
struct asio_context_service
: Context::service
, capy::execution_context
{
static Context::id id;

asio_context_service(Context & ctx)
: Context::service(ctx) {}
void shutdown() override {capy::execution_context::shutdown();}
};


// asio_context_service is templated for this id.
template<typename Context>
Context::id asio_context_service<Context>::id;

}

#endif
49 changes: 49 additions & 0 deletions include/boost/capy/asio/detail/asio_coroutine_unique_handle.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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)
//
// Official repository: https://github.com/cppalliance/capy
//


#ifndef BOOST_CAPY_ASIO_DETAIL_ASIO_COROUTINE_UNIQUE_HANDLE
#define BOOST_CAPY_ASIO_DETAIL_ASIO_COROUTINE_UNIQUE_HANDLE

#include <coroutine>
#include <memory>

namespace boost::capy::detail
{

struct asio_coroutine_unique_handle
{
struct deleter
{
deleter() = default;
void operator()(void * h) const
{
std::coroutine_handle<void>::from_address(h).destroy();
}
};
std::unique_ptr<void, deleter> handle;

asio_coroutine_unique_handle(
std::coroutine_handle<void> h) : handle(h.address()) {}

asio_coroutine_unique_handle(
asio_coroutine_unique_handle &&
) noexcept = default;

void operator()()
{
std::coroutine_handle<void>::from_address(
handle.release()
).resume();
}
};

}

#endif
134 changes: 134 additions & 0 deletions include/boost/capy/asio/detail/completion_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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)
//
// Official repository: https://github.com/cppalliance/capy
//

#ifndef BOOST_CAPY_ASIO_DETAIL_COMPLETION_HANDLER
#define BOOST_CAPY_ASIO_DETAIL_COMPLETION_HANDLER

#include <boost/capy/asio/detail/asio_coroutine_unique_handle.hpp>
#include <boost/capy/asio/executor_adapter.hpp>
#include <boost/capy/ex/executor_ref.hpp>
#include <boost/capy/ex/io_env.hpp>

#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/post.hpp>

#include <memory_resource>
#include <optional>
#include <tuple>

namespace boost::capy::detail
{


struct asio_immediate_executor_helper
{
enum completed_immediately_t
{
no, maybe, yes, initiating
};

asio_executor_adapter<executor_ref> exec;
completed_immediately_t * completed_immediately = nullptr;

template<typename Fn>
void execute(Fn && fn) const
{
// only allow it when we're still initializing
if (completed_immediately &&
((*completed_immediately == initiating)
|| (*completed_immediately == maybe)))
{
// only use this indicator if the fn will actually call our completion-handler
// otherwise this was a single op in a composed operation
*completed_immediately = maybe;
fn();

if (*completed_immediately != yes)
*completed_immediately = initiating;
}
else
{
boost::asio::post(exec, std::forward<Fn>(fn));
}
}

friend bool operator==(const asio_immediate_executor_helper& lhs,
const asio_immediate_executor_helper& rhs) noexcept
{
return lhs.exec == rhs.exec;
}

friend bool operator!=(const asio_immediate_executor_helper& lhs,
const asio_immediate_executor_helper& rhs) noexcept
{
return lhs.exec != rhs.exec;
}

asio_immediate_executor_helper(const asio_immediate_executor_helper & rhs) noexcept = default;
asio_immediate_executor_helper(executor_ref inner, completed_immediately_t * completed_immediately)
: exec(std::move(inner)), completed_immediately(completed_immediately)
{
}
};


template<typename ... Args>
struct asio_coroutine_completion_handler
{
struct deleter
{
deleter() = default;
void operator()(void * h) const
{
std::coroutine_handle<void>::from_address(h).destroy();
}
};
asio_coroutine_unique_handle handle;
std::optional<std::tuple<Args...>> & result;
capy::io_env * env;
boost::asio::cancellation_slot slot;
asio_immediate_executor_helper::completed_immediately_t * completed_immediately = nullptr;

using allocator_type = std::pmr::polymorphic_allocator<void>;
allocator_type get_allocator() const {return env->frame_allocator;}

using executor_type = asio_executor_adapter<executor_ref>;
executor_type get_executor() const {return env->executor;}

using cancellation_slot_type = boost::asio::cancellation_slot;
cancellation_slot_type get_cancellation_slot() const {return slot;}

using immediate_executor_type = asio_immediate_executor_helper;
immediate_executor_type get_immediate_executor() const
{
return immediate_executor_type{env->executor, completed_immediately };
};

asio_coroutine_completion_handler(
std::coroutine_handle<void> h,
std::optional<std::tuple<Args...>> & result,
capy::io_env * env,
boost::asio::cancellation_slot slot = {},
asio_immediate_executor_helper::completed_immediately_t * ci = nullptr)
: handle(h), result(result), env(env), slot(slot), completed_immediately(ci) {}

asio_coroutine_completion_handler(
asio_coroutine_completion_handler &&
) noexcept = default;

void operator()(Args ... args)
{
result.emplace(std::forward<Args>(args)...);
std::move(handle)();
}
};

}

#endif //BOOST_CAPY_ASIO_DETAIL_COMPLETION_HANDLER
134 changes: 134 additions & 0 deletions include/boost/capy/asio/detail/standalone_completion_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//
// Copyright (c) 2026 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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)
//
// Official repository: https://github.com/cppalliance/capy
//

#ifndef BOOST_CAPY_ASIO_DETAIL_STANDALONE_COMPLETION_HANDLER
#define BOOST_CAPY_ASIO_DETAIL_STANDALONE_COMPLETION_HANDLER

#include <boost/capy/asio/detail/asio_coroutine_unique_handle.hpp>
#include <boost/capy/asio/standalone_executor_adapter.hpp>
#include <boost/capy/ex/executor_ref.hpp>
#include <boost/capy/ex/io_env.hpp>

#include <asio/cancellation_signal.hpp>
#include <asio/post.hpp>

#include <memory_resource>
#include <optional>
#include <tuple>

namespace boost::capy::detail
{


struct standalone_asio_immediate_executor_helper
{
enum completed_immediately_t
{
no, maybe, yes, initiating
};

standalone_asio_executor_adapter<executor_ref> exec;
completed_immediately_t * completed_immediately = nullptr;

template<typename Fn>
void execute(Fn && fn) const
{
// only allow it when we're still initializing
if (completed_immediately &&
((*completed_immediately == initiating)
|| (*completed_immediately == maybe)))
{
// only use this indicator if the fn will actually call our completion-handler
// otherwise this was a single op in a composed operation
*completed_immediately = maybe;
fn();

if (*completed_immediately != yes)
*completed_immediately = initiating;
}
else
{
::asio::post(exec, std::forward<Fn>(fn));
}
}

friend bool operator==(const standalone_asio_immediate_executor_helper& lhs,
const standalone_asio_immediate_executor_helper& rhs) noexcept
{
return lhs.exec == rhs.exec;
}

friend bool operator!=(const standalone_asio_immediate_executor_helper& lhs,
const standalone_asio_immediate_executor_helper& rhs) noexcept
{
return lhs.exec == rhs.exec;
}

standalone_asio_immediate_executor_helper(const standalone_asio_immediate_executor_helper & rhs) noexcept = default;
standalone_asio_immediate_executor_helper(executor_ref inner, completed_immediately_t * completed_immediately)
: exec(std::move(inner)), completed_immediately(completed_immediately)
{
}
};


template<typename ... Args>
struct standalone_asio_coroutine_completion_handler
{
struct deleter
{
deleter() = default;
void operator()(void * h) const
{
std::coroutine_handle<void>::from_address(h).destroy();
}
};
asio_coroutine_unique_handle handle;
std::optional<std::tuple<Args...>> & result;
capy::io_env * env;
::asio::cancellation_slot slot;
standalone_asio_immediate_executor_helper::completed_immediately_t * completed_immediately = nullptr;

using allocator_type = std::pmr::polymorphic_allocator<void>;
allocator_type get_allocator() const {return env->frame_allocator;}

using executor_type = standalone_asio_executor_adapter<executor_ref>;
executor_type get_executor() const {return env->executor;}

using cancellation_slot_type = ::asio::cancellation_slot;
cancellation_slot_type get_cancellation_slot() const {return slot;}

using immediate_executor_type = standalone_asio_immediate_executor_helper;
immediate_executor_type get_immediate_executor() const
{
return immediate_executor_type{env->executor, completed_immediately };
};

standalone_asio_coroutine_completion_handler(
std::coroutine_handle<void> h,
std::optional<std::tuple<Args...>> & result,
capy::io_env * env,
::asio::cancellation_slot slot = {},
standalone_asio_immediate_executor_helper::completed_immediately_t * ci = nullptr)
: handle(h), result(result), env(env), slot(slot), completed_immediately(ci) {}

standalone_asio_coroutine_completion_handler(
standalone_asio_coroutine_completion_handler &&
) noexcept = default;

void operator()(Args ... args)
{
result.emplace(std::forward<Args>(args)...);
std::move(handle)();
}
};

}

#endif //BOOST_CAPY_ASIO_DETAIL_COMPLETION_HANDLER
Loading
Loading