1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/corosio
7  
// Official repository: https://github.com/cppalliance/corosio
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_COROSIO_IO_OBJECT_HPP
10  
#ifndef BOOST_COROSIO_IO_OBJECT_HPP
11  
#define BOOST_COROSIO_IO_OBJECT_HPP
11  
#define BOOST_COROSIO_IO_OBJECT_HPP
12  

12  

13  
#include <boost/corosio/detail/config.hpp>
13  
#include <boost/corosio/detail/config.hpp>
14  
#include <boost/capy/ex/execution_context.hpp>
14  
#include <boost/capy/ex/execution_context.hpp>
15  

15  

16  
namespace boost::corosio {
16  
namespace boost::corosio {
17  

17  

18  
/** Base class for platform I/O objects.
18  
/** Base class for platform I/O objects.
19  

19  

20  
    Provides common infrastructure for I/O objects that wrap kernel
20  
    Provides common infrastructure for I/O objects that wrap kernel
21  
    resources (sockets, timers, signal handlers, acceptors). Derived
21  
    resources (sockets, timers, signal handlers, acceptors). Derived
22  
    classes dispatch operations through a platform-specific vtable
22  
    classes dispatch operations through a platform-specific vtable
23  
    (IOCP, epoll, kqueue, io_uring).
23  
    (IOCP, epoll, kqueue, io_uring).
24  

24  

25  
    @par Semantics
25  
    @par Semantics
26  
    Only concrete platform I/O types should inherit from `io_object`.
26  
    Only concrete platform I/O types should inherit from `io_object`.
27  
    Test mocks, decorators, and stream adapters must not inherit from
27  
    Test mocks, decorators, and stream adapters must not inherit from
28  
    this class. Use concepts or templates for generic I/O algorithms.
28  
    this class. Use concepts or templates for generic I/O algorithms.
29  

29  

30  
    @par Thread Safety
30  
    @par Thread Safety
31  
    Distinct objects: Safe.
31  
    Distinct objects: Safe.
32  
    Shared objects: Unsafe. All operations on a single I/O object
32  
    Shared objects: Unsafe. All operations on a single I/O object
33  
    must be serialized.
33  
    must be serialized.
34  

34  

35  
    @note Intended as a protected base class. The implementation
35  
    @note Intended as a protected base class. The implementation
36  
        pointer `impl_` is accessible to derived classes.
36  
        pointer `impl_` is accessible to derived classes.
37  

37  

38  
    @see io_stream, tcp_socket, tcp_acceptor
38  
    @see io_stream, tcp_socket, tcp_acceptor
39  
*/
39  
*/
40  
class BOOST_COROSIO_DECL io_object
40  
class BOOST_COROSIO_DECL io_object
41  
{
41  
{
42  
public:
42  
public:
43  
    /// Forward declaration for platform-specific implementation.
43  
    /// Forward declaration for platform-specific implementation.
44  
    struct implementation;
44  
    struct implementation;
45  

45  

46  
    class handle;
46  
    class handle;
47  

47  

48  
    /** Service interface for I/O object lifecycle management.
48  
    /** Service interface for I/O object lifecycle management.
49  

49  

50  
        Platform backends implement this interface to manage the
50  
        Platform backends implement this interface to manage the
51  
        creation, opening, closing, and destruction of I/O object
51  
        creation, opening, closing, and destruction of I/O object
52  
        implementations.
52  
        implementations.
53  
    */
53  
    */
54  
    struct io_service
54  
    struct io_service
55  
    {
55  
    {
56  
        /// Open the I/O object for use.
56  
        /// Open the I/O object for use.
57  
        virtual void open(handle&) = 0;
57  
        virtual void open(handle&) = 0;
58  

58  

59  
        /// Close the I/O object, releasing kernel resources.
59  
        /// Close the I/O object, releasing kernel resources.
60  
        virtual void close(handle&) = 0;
60  
        virtual void close(handle&) = 0;
61  

61  

62  
        /// Destroy the implementation, freeing memory.
62  
        /// Destroy the implementation, freeing memory.
63  
        virtual void destroy(implementation*) = 0;
63  
        virtual void destroy(implementation*) = 0;
64  

64  

65  
        /// Construct a new implementation instance.
65  
        /// Construct a new implementation instance.
66  
        virtual implementation* construct() = 0;
66  
        virtual implementation* construct() = 0;
67  
    };
67  
    };
68  

68  

69  
    /** RAII wrapper for I/O object implementation lifetime.
69  
    /** RAII wrapper for I/O object implementation lifetime.
70  

70  

71  
        Manages ownership of the platform-specific implementation,
71  
        Manages ownership of the platform-specific implementation,
72  
        automatically destroying it when the handle goes out of scope.
72  
        automatically destroying it when the handle goes out of scope.
73  
    */
73  
    */
74  
    class handle
74  
    class handle
75  
    {
75  
    {
76  
        capy::execution_context* ctx_ = nullptr;
76  
        capy::execution_context* ctx_ = nullptr;
77  
        io_service* svc_ = nullptr;
77  
        io_service* svc_ = nullptr;
78  
        implementation* impl_ = nullptr;
78  
        implementation* impl_ = nullptr;
79  

79  

80  
    public:
80  
    public:
81  
        /// Destroy the handle and its implementation.
81  
        /// Destroy the handle and its implementation.
82  
        ~handle()
82  
        ~handle()
83  
        {
83  
        {
84  
            if(impl_)
84  
            if(impl_)
85  
                svc_->destroy(impl_);
85  
                svc_->destroy(impl_);
86  
        }
86  
        }
87  

87  

88  
        /// Construct an empty handle.
88  
        /// Construct an empty handle.
89  
        handle() = default;
89  
        handle() = default;
90  

90  

91  
        /// Construct a handle bound to a context and service.
91  
        /// Construct a handle bound to a context and service.
92  
        handle(
92  
        handle(
93  
            capy::execution_context& ctx,
93  
            capy::execution_context& ctx,
94  
            io_service& svc)
94  
            io_service& svc)
95  
            : ctx_(&ctx)
95  
            : ctx_(&ctx)
96  
            , svc_(&svc)
96  
            , svc_(&svc)
97  
            , impl_(svc_->construct())
97  
            , impl_(svc_->construct())
98  
        {
98  
        {
99  
        }
99  
        }
100  

100  

101  
        /// Move construct from another handle.
101  
        /// Move construct from another handle.
102  
        handle(handle&& other)
102  
        handle(handle&& other)
103  
            : ctx_(std::exchange(other.ctx_, nullptr))
103  
            : ctx_(std::exchange(other.ctx_, nullptr))
104  
            , svc_(std::exchange(other.svc_, nullptr))
104  
            , svc_(std::exchange(other.svc_, nullptr))
105  
            , impl_(std::exchange(other.impl_, nullptr))
105  
            , impl_(std::exchange(other.impl_, nullptr))
106  
        {
106  
        {
107  
        }
107  
        }
108  

108  

109  
        /// Move assign from another handle.
109  
        /// Move assign from another handle.
110  
        handle& operator=(handle&& other) noexcept
110  
        handle& operator=(handle&& other) noexcept
111  
        {
111  
        {
112  
            ctx_ = std::exchange(other.ctx_, nullptr);
112  
            ctx_ = std::exchange(other.ctx_, nullptr);
113  
            svc_ = std::exchange(other.svc_, nullptr);
113  
            svc_ = std::exchange(other.svc_, nullptr);
114  
            impl_ = std::exchange(other.impl_, nullptr);
114  
            impl_ = std::exchange(other.impl_, nullptr);
115  
            return *this;
115  
            return *this;
116  
        }
116  
        }
117  

117  

118  
        /// Return the execution context.
118  
        /// Return the execution context.
119  
        capy::execution_context& context() const noexcept
119  
        capy::execution_context& context() const noexcept
120  
        {
120  
        {
121  
            return *ctx_;
121  
            return *ctx_;
122  
        }
122  
        }
123  

123  

124  
        /// Return the associated I/O service.
124  
        /// Return the associated I/O service.
125  
        io_service& service() const noexcept
125  
        io_service& service() const noexcept
126  
        {
126  
        {
127  
            return *svc_;
127  
            return *svc_;
128  
        }
128  
        }
129  

129  

130  
        /// Return the platform implementation.
130  
        /// Return the platform implementation.
131  
        implementation& get() const noexcept
131  
        implementation& get() const noexcept
132  
        {
132  
        {
133  
            return *impl_;
133  
            return *impl_;
134  
        }
134  
        }
135  
    };
135  
    };
136  

136  

137  
    /** Base interface for platform I/O implementations.
137  
    /** Base interface for platform I/O implementations.
138  

138  

139  
        Derived classes provide platform-specific operation dispatch.
139  
        Derived classes provide platform-specific operation dispatch.
140  
    */
140  
    */
141  
    struct io_object_impl
141  
    struct io_object_impl
142  
    {
142  
    {
143  
        virtual ~io_object_impl() = default;
143  
        virtual ~io_object_impl() = default;
144  

144  

145  
        /// Release associated resources without closing.
145  
        /// Release associated resources without closing.
146  
        virtual void release() = 0;
146  
        virtual void release() = 0;
147  
    };
147  
    };
148  

148  

149  
    /// Return the execution context.
149  
    /// Return the execution context.
150  
    capy::execution_context&
150  
    capy::execution_context&
151  
    context() const noexcept
151  
    context() const noexcept
152  
    {
152  
    {
153  
        return *ctx_;
153  
        return *ctx_;
154  
    }
154  
    }
155  

155  

156  
protected:
156  
protected:
157  
    virtual ~io_object() = default;
157  
    virtual ~io_object() = default;
158  

158  

159  
    /// Construct an I/O object bound to the given context.
159  
    /// Construct an I/O object bound to the given context.
160  
    explicit
160  
    explicit
161  
    io_object(
161  
    io_object(
162  
        capy::execution_context& ctx) noexcept
162  
        capy::execution_context& ctx) noexcept
163  
        : ctx_(&ctx)
163  
        : ctx_(&ctx)
164  
    {
164  
    {
165  
    }
165  
    }
166  

166  

167  
    capy::execution_context* ctx_ = nullptr;
167  
    capy::execution_context* ctx_ = nullptr;
168  
    io_object_impl* impl_ = nullptr;
168  
    io_object_impl* impl_ = nullptr;
169  
};
169  
};
170  

170  

171  
} // namespace boost::corosio
171  
} // namespace boost::corosio
172  

172  

173  
#endif
173  
#endif