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
18 changes: 10 additions & 8 deletions src/corosio/src/acceptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

#include <boost/corosio/acceptor.hpp>

#ifdef _WIN32
#include "src/detail/win/sockets.hpp"
#else
#include "detail/posix_sockets.hpp"
#include "src/detail/config_backend.hpp"

#if defined(BOOST_COROSIO_BACKEND_IOCP)
#include "src/detail/iocp/sockets.hpp"
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
#include "src/detail/epoll/sockets.hpp"
#endif

#include <boost/corosio/detail/except.hpp>
Expand All @@ -23,12 +25,12 @@ namespace boost {
namespace corosio {
namespace {

#ifdef _WIN32
#if defined(BOOST_COROSIO_BACKEND_IOCP)
using acceptor_service = detail::win_sockets;
using acceptor_impl_type = detail::win_acceptor_impl;
#else
using acceptor_service = detail::posix_sockets;
using acceptor_impl_type = detail::posix_acceptor_impl;
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
using acceptor_service = detail::epoll_sockets;
using acceptor_impl_type = detail::epoll_acceptor_impl;
#endif

} // namespace
Expand Down
50 changes: 50 additions & 0 deletions src/corosio/src/detail/config_backend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Copyright (c) 2026 Steve Gerbino
//
// 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/corosio
//

#ifndef BOOST_COROSIO_DETAIL_CONFIG_BACKEND_HPP
#define BOOST_COROSIO_DETAIL_CONFIG_BACKEND_HPP

//
// Backend selection for I/O multiplexing and signal handling.
//
// I/O Backends:
// BOOST_COROSIO_BACKEND_IOCP - Windows I/O Completion Ports
// BOOST_COROSIO_BACKEND_EPOLL - Linux epoll
// BOOST_COROSIO_BACKEND_IO_URING - Linux io_uring (future)
// BOOST_COROSIO_BACKEND_KQUEUE - BSD/macOS kqueue (future)
// BOOST_COROSIO_BACKEND_POLL - POSIX poll fallback (future)
//
// Signal Backends:
// BOOST_COROSIO_SIGNAL_WIN - Windows (SetConsoleCtrlHandler + signal)
// BOOST_COROSIO_SIGNAL_POSIX - POSIX (sigaction)
//

#if defined(_WIN32)
#define BOOST_COROSIO_BACKEND_IOCP 1
#define BOOST_COROSIO_SIGNAL_WIN 1
#elif defined(__linux__)
#if defined(BOOST_COROSIO_USE_IO_URING)
#define BOOST_COROSIO_BACKEND_IO_URING 1
#else
#define BOOST_COROSIO_BACKEND_EPOLL 1
#endif
#define BOOST_COROSIO_SIGNAL_POSIX 1
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define BOOST_COROSIO_BACKEND_KQUEUE 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#elif defined(__APPLE__)
#define BOOST_COROSIO_BACKEND_KQUEUE 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#else
// Fallback to poll for other POSIX systems
#define BOOST_COROSIO_BACKEND_POLL 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#endif
Comment on lines +28 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Allow explicit backend overrides and prevent multiple backend defines.

This block always defines platform defaults, which defeats explicit backend selection and can yield multiple BOOST_COROSIO_BACKEND_* macros (e.g., user-defined IO_URING plus default EPOLL). That leads to ambiguous downstream #if selection. Consider only defining defaults when no backend is already selected and add a single-backend sanity check.

🛠️ Proposed fix (guard defaults + single-backend check)
-#if defined(_WIN32)
-    `#define` BOOST_COROSIO_BACKEND_IOCP 1
-    `#define` BOOST_COROSIO_SIGNAL_WIN 1
-#elif defined(__linux__)
-    `#if` defined(BOOST_COROSIO_USE_IO_URING)
-        `#define` BOOST_COROSIO_BACKEND_IO_URING 1
-    `#else`
-        `#define` BOOST_COROSIO_BACKEND_EPOLL 1
-    `#endif`
-    `#define` BOOST_COROSIO_SIGNAL_POSIX 1
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
-    `#define` BOOST_COROSIO_BACKEND_KQUEUE 1
-    `#define` BOOST_COROSIO_SIGNAL_POSIX 1
-#elif defined(__APPLE__)
-    `#define` BOOST_COROSIO_BACKEND_KQUEUE 1
-    `#define` BOOST_COROSIO_SIGNAL_POSIX 1
-#else
-    // Fallback to poll for other POSIX systems
-    `#define` BOOST_COROSIO_BACKEND_POLL 1
-    `#define` BOOST_COROSIO_SIGNAL_POSIX 1
-#endif
+#if !defined(BOOST_COROSIO_BACKEND_IOCP) && \
+    !defined(BOOST_COROSIO_BACKEND_EPOLL) && \
+    !defined(BOOST_COROSIO_BACKEND_IO_URING) && \
+    !defined(BOOST_COROSIO_BACKEND_KQUEUE) && \
+    !defined(BOOST_COROSIO_BACKEND_POLL)
+    `#if` defined(_WIN32)
+        `#define` BOOST_COROSIO_BACKEND_IOCP 1
+    `#elif` defined(__linux__)
+        `#if` defined(BOOST_COROSIO_USE_IO_URING)
+            `#define` BOOST_COROSIO_BACKEND_IO_URING 1
+        `#else`
+            `#define` BOOST_COROSIO_BACKEND_EPOLL 1
+        `#endif`
+    `#elif` defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+        `#define` BOOST_COROSIO_BACKEND_KQUEUE 1
+    `#elif` defined(__APPLE__)
+        `#define` BOOST_COROSIO_BACKEND_KQUEUE 1
+    `#else`
+        // Fallback to poll for other POSIX systems
+        `#define` BOOST_COROSIO_BACKEND_POLL 1
+    `#endif`
+#endif
+
+#if defined(_WIN32)
+    `#ifndef` BOOST_COROSIO_SIGNAL_WIN
+    `#define` BOOST_COROSIO_SIGNAL_WIN 1
+    `#endif`
+#else
+    `#ifndef` BOOST_COROSIO_SIGNAL_POSIX
+    `#define` BOOST_COROSIO_SIGNAL_POSIX 1
+    `#endif`
+#endif
+
+#if (defined(BOOST_COROSIO_BACKEND_IOCP) + defined(BOOST_COROSIO_BACKEND_EPOLL) + \
+     defined(BOOST_COROSIO_BACKEND_IO_URING) + defined(BOOST_COROSIO_BACKEND_KQUEUE) + \
+     defined(BOOST_COROSIO_BACKEND_POLL)) != 1
+#error "Select exactly one BOOST_COROSIO_BACKEND_*"
+#endif
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#if defined(_WIN32)
#define BOOST_COROSIO_BACKEND_IOCP 1
#define BOOST_COROSIO_SIGNAL_WIN 1
#elif defined(__linux__)
#if defined(BOOST_COROSIO_USE_IO_URING)
#define BOOST_COROSIO_BACKEND_IO_URING 1
#else
#define BOOST_COROSIO_BACKEND_EPOLL 1
#endif
#define BOOST_COROSIO_SIGNAL_POSIX 1
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define BOOST_COROSIO_BACKEND_KQUEUE 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#elif defined(__APPLE__)
#define BOOST_COROSIO_BACKEND_KQUEUE 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#else
// Fallback to poll for other POSIX systems
#define BOOST_COROSIO_BACKEND_POLL 1
#define BOOST_COROSIO_SIGNAL_POSIX 1
#endif
`#if` !defined(BOOST_COROSIO_BACKEND_IOCP) && \
!defined(BOOST_COROSIO_BACKEND_EPOLL) && \
!defined(BOOST_COROSIO_BACKEND_IO_URING) && \
!defined(BOOST_COROSIO_BACKEND_KQUEUE) && \
!defined(BOOST_COROSIO_BACKEND_POLL)
`#if` defined(_WIN32)
`#define` BOOST_COROSIO_BACKEND_IOCP 1
`#elif` defined(__linux__)
`#if` defined(BOOST_COROSIO_USE_IO_URING)
`#define` BOOST_COROSIO_BACKEND_IO_URING 1
`#else`
`#define` BOOST_COROSIO_BACKEND_EPOLL 1
`#endif`
`#elif` defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
`#define` BOOST_COROSIO_BACKEND_KQUEUE 1
`#elif` defined(__APPLE__)
`#define` BOOST_COROSIO_BACKEND_KQUEUE 1
`#else`
// Fallback to poll for other POSIX systems
`#define` BOOST_COROSIO_BACKEND_POLL 1
`#endif`
`#endif`
`#if` defined(_WIN32)
`#ifndef` BOOST_COROSIO_SIGNAL_WIN
`#define` BOOST_COROSIO_SIGNAL_WIN 1
`#endif`
`#else`
`#ifndef` BOOST_COROSIO_SIGNAL_POSIX
`#define` BOOST_COROSIO_SIGNAL_POSIX 1
`#endif`
`#endif`
`#if` (defined(BOOST_COROSIO_BACKEND_IOCP) + defined(BOOST_COROSIO_BACKEND_EPOLL) + \
defined(BOOST_COROSIO_BACKEND_IO_URING) + defined(BOOST_COROSIO_BACKEND_KQUEUE) + \
defined(BOOST_COROSIO_BACKEND_POLL)) != 1
`#error` "Select exactly one BOOST_COROSIO_BACKEND_*"
`#endif`
🤖 Prompt for AI Agents
In `@src/corosio/src/detail/config_backend.hpp` around lines 28 - 48, The platform
defaulting in config_backend.hpp unconditionally defines BOOST_COROSIO_BACKEND_*
and thus overrides user overrides and can produce multiple backend macros;
change the logic so defaults are only defined when none of the backend macros
(e.g., BOOST_COROSIO_BACKEND_IOCP, BOOST_COROSIO_BACKEND_IO_URING,
BOOST_COROSIO_BACKEND_EPOLL, BOOST_COROSIO_BACKEND_KQUEUE,
BOOST_COROSIO_BACKEND_POLL) are already defined, and add a compile-time sanity
check that triggers a preprocessor error if more than one
BOOST_COROSIO_BACKEND_* is defined (or none after platform/default resolution);
update the platform branches (the `#if` defined(_WIN32), __linux__, __APPLE__, BSD
branch, and the fallback) to guard their `#define` with a prior check for existing
backend defines and add a final block that checks for multiple definitions and
emits `#error` if found.


#endif // BOOST_COROSIO_DETAIL_CONFIG_BACKEND_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
// Official repository: https://github.com/cppalliance/corosio
//

#ifndef BOOST_COROSIO_DETAIL_POSIX_OP_HPP
#define BOOST_COROSIO_DETAIL_POSIX_OP_HPP
#ifndef BOOST_COROSIO_DETAIL_EPOLL_OP_HPP
#define BOOST_COROSIO_DETAIL_EPOLL_OP_HPP

#include "src/detail/config_backend.hpp"

#if defined(BOOST_COROSIO_BACKEND_EPOLL)

#include <boost/corosio/detail/config.hpp>
#include <boost/corosio/io_object.hpp>
Expand Down Expand Up @@ -37,17 +41,17 @@ namespace boost {
namespace corosio {
namespace detail {

/** Base class for POSIX async operations.
/** Base class for epoll async operations.

This class is analogous to overlapped_op on Windows.
It stores the coroutine handle, executor, and result
pointers needed to complete an async operation.
*/
struct posix_op : scheduler_op
struct epoll_op : scheduler_op
{
struct canceller
{
posix_op* op;
epoll_op* op;
void operator()() const noexcept { op->request_cancel(); }
};

Expand All @@ -64,7 +68,7 @@ struct posix_op : scheduler_op
std::atomic<bool> cancelled{false};
std::optional<std::stop_callback<canceller>> stop_cb;

posix_op()
epoll_op()
{
data_ = this;
}
Expand Down Expand Up @@ -135,16 +139,16 @@ struct posix_op : scheduler_op
virtual void perform_io() noexcept {}
};

inline posix_op*
get_posix_op(scheduler_op* h) noexcept
inline epoll_op*
get_epoll_op(scheduler_op* h) noexcept
{
return static_cast<posix_op*>(h->data());
return static_cast<epoll_op*>(h->data());
}

//------------------------------------------------------------------------------

/** Connect operation state. */
struct posix_connect_op : posix_op
struct epoll_connect_op : epoll_op
{
void perform_io() noexcept override
{
Expand All @@ -160,7 +164,7 @@ struct posix_connect_op : posix_op
//------------------------------------------------------------------------------

/** Read operation state with buffer descriptors. */
struct posix_read_op : posix_op
struct epoll_read_op : epoll_op
{
static constexpr std::size_t max_buffers = 16;
iovec iovecs[max_buffers];
Expand All @@ -170,7 +174,7 @@ struct posix_read_op : posix_op

void reset() noexcept
{
posix_op::reset();
epoll_op::reset();
iovec_count = 0;
}

Expand All @@ -187,15 +191,15 @@ struct posix_read_op : posix_op
//------------------------------------------------------------------------------

/** Write operation state with buffer descriptors. */
struct posix_write_op : posix_op
struct epoll_write_op : epoll_op
{
static constexpr std::size_t max_buffers = 16;
iovec iovecs[max_buffers];
int iovec_count = 0;

void reset() noexcept
{
posix_op::reset();
epoll_op::reset();
iovec_count = 0;
}

Expand All @@ -212,7 +216,7 @@ struct posix_write_op : posix_op
//------------------------------------------------------------------------------

/** Accept operation state. */
struct posix_accept_op : posix_op
struct epoll_accept_op : epoll_op
{
int accepted_fd = -1;
io_object::io_object_impl* peer_impl = nullptr;
Expand All @@ -224,7 +228,7 @@ struct posix_accept_op : posix_op

void reset() noexcept
{
posix_op::reset();
epoll_op::reset();
accepted_fd = -1;
peer_impl = nullptr;
impl_out = nullptr;
Expand Down Expand Up @@ -297,4 +301,6 @@ struct posix_accept_op : posix_op
} // namespace corosio
} // namespace boost

#endif
#endif // BOOST_COROSIO_BACKEND_EPOLL

#endif // BOOST_COROSIO_DETAIL_EPOLL_OP_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
// Official repository: https://github.com/cppalliance/corosio
//

#ifndef BOOST_COROSIO_DETAIL_POSIX_RESOLVER_SERVICE_HPP
#define BOOST_COROSIO_DETAIL_POSIX_RESOLVER_SERVICE_HPP
#ifndef BOOST_COROSIO_DETAIL_EPOLL_RESOLVER_SERVICE_HPP
#define BOOST_COROSIO_DETAIL_EPOLL_RESOLVER_SERVICE_HPP

#include "src/detail/config_backend.hpp"

#if defined(BOOST_COROSIO_BACKEND_EPOLL)

#include <boost/corosio/detail/config.hpp>
#include <boost/corosio/resolver.hpp>
Expand All @@ -25,27 +29,27 @@ namespace boost {
namespace corosio {
namespace detail {

class posix_resolver_service;
class posix_resolver_impl;
class epoll_resolver_service;
class epoll_resolver_impl;

//------------------------------------------------------------------------------

/** Resolver implementation stub for POSIX platforms.
/** Resolver implementation stub for Linux.

This is a placeholder implementation that allows compilation on
POSIX platforms. Operations throw std::logic_error indicating
the functionality is not yet implemented.
Linux. Operations throw std::logic_error indicating the
functionality is not yet implemented.

@note Full POSIX resolver support is planned for a future release.
@note Full resolver support is planned for a future release.
*/
class posix_resolver_impl
class epoll_resolver_impl
: public resolver::resolver_impl
, public capy::intrusive_list<posix_resolver_impl>::node
, public capy::intrusive_list<epoll_resolver_impl>::node
{
friend class posix_resolver_service;
friend class epoll_resolver_service;

public:
explicit posix_resolver_impl(posix_resolver_service& svc) noexcept
explicit epoll_resolver_impl(epoll_resolver_service& svc) noexcept
: svc_(svc)
{
}
Expand All @@ -62,45 +66,45 @@ class posix_resolver_impl
system::error_code*,
resolver_results*) override
{
throw std::logic_error("posix resolver resolve not implemented");
throw std::logic_error("epoll resolver resolve not implemented");
}

void cancel() noexcept { /* stub */ }

private:
posix_resolver_service& svc_;
epoll_resolver_service& svc_;
};

//------------------------------------------------------------------------------

/** POSIX resolver service stub.
/** Linux resolver service stub.

This service provides placeholder implementations for DNS
resolution on POSIX platforms. Operations throw std::logic_error.
resolution on Linux. Operations throw std::logic_error.

@note Full POSIX resolver support is planned for a future release.
@note Full resolver support is planned for a future release.
*/
class posix_resolver_service
class epoll_resolver_service
: public capy::execution_context::service
{
public:
using key_type = posix_resolver_service;
using key_type = epoll_resolver_service;

/** Construct the resolver service.

@param ctx Reference to the owning execution_context.
*/
explicit posix_resolver_service(capy::execution_context& /*ctx*/)
explicit epoll_resolver_service(capy::execution_context& /*ctx*/)
{
}

/** Destroy the resolver service. */
~posix_resolver_service()
~epoll_resolver_service()
{
}

posix_resolver_service(posix_resolver_service const&) = delete;
posix_resolver_service& operator=(posix_resolver_service const&) = delete;
epoll_resolver_service(epoll_resolver_service const&) = delete;
epoll_resolver_service& operator=(epoll_resolver_service const&) = delete;

/** Shut down the service. */
void shutdown() override
Expand All @@ -115,16 +119,16 @@ class posix_resolver_service
}

/** Create a new resolver implementation. */
posix_resolver_impl& create_impl()
epoll_resolver_impl& create_impl()
{
std::lock_guard lock(mutex_);
auto* impl = new posix_resolver_impl(*this);
auto* impl = new epoll_resolver_impl(*this);
resolver_list_.push_back(impl);
return *impl;
}

/** Destroy a resolver implementation. */
void destroy_impl(posix_resolver_impl& impl)
void destroy_impl(epoll_resolver_impl& impl)
{
std::lock_guard lock(mutex_);
resolver_list_.remove(&impl);
Expand All @@ -133,13 +137,13 @@ class posix_resolver_service

private:
std::mutex mutex_;
capy::intrusive_list<posix_resolver_impl> resolver_list_;
capy::intrusive_list<epoll_resolver_impl> resolver_list_;
};

//------------------------------------------------------------------------------

inline void
posix_resolver_impl::
epoll_resolver_impl::
release()
{
svc_.destroy_impl(*this);
Expand All @@ -149,4 +153,6 @@ release()
} // namespace corosio
} // namespace boost

#endif
#endif // BOOST_COROSIO_BACKEND_EPOLL

#endif // BOOST_COROSIO_DETAIL_EPOLL_RESOLVER_SERVICE_HPP
Loading
Loading