1 //
2 // windows/overlapped_ptr.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef BOOST_ASIO_WINDOWS_OVERLAPPED_PTR_HPP
12 #define BOOST_ASIO_WINDOWS_OVERLAPPED_PTR_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 
20 #if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
21   || defined(GENERATING_DOCUMENTATION)
22 
23 #include <boost/asio/detail/noncopyable.hpp>
24 #include <boost/asio/detail/win_iocp_overlapped_ptr.hpp>
25 #include <boost/asio/io_context.hpp>
26 
27 #include <boost/asio/detail/push_options.hpp>
28 
29 namespace boost {
30 namespace asio {
31 namespace windows {
32 
33 /// Wraps a handler to create an OVERLAPPED object for use with overlapped I/O.
34 /**
35  * A special-purpose smart pointer used to wrap an application handler so that
36  * it can be passed as the LPOVERLAPPED argument to overlapped I/O functions.
37  *
38  * @par Thread Safety
39  * @e Distinct @e objects: Safe.@n
40  * @e Shared @e objects: Unsafe.
41  */
42 class overlapped_ptr
43   : private noncopyable
44 {
45 public:
46   /// Construct an empty overlapped_ptr.
overlapped_ptr()47   overlapped_ptr()
48     : impl_()
49   {
50   }
51 
52   /// Construct an overlapped_ptr to contain the specified handler.
53   template <typename ExecutionContext, typename Handler>
overlapped_ptr(ExecutionContext & context,BOOST_ASIO_MOVE_ARG (Handler)handler,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)54   explicit overlapped_ptr(ExecutionContext& context,
55       BOOST_ASIO_MOVE_ARG(Handler) handler,
56       typename constraint<
57         is_convertible<ExecutionContext&, execution_context&>::value
58       >::type = 0)
59     : impl_(context.get_executor(), BOOST_ASIO_MOVE_CAST(Handler)(handler))
60   {
61   }
62 
63   /// Construct an overlapped_ptr to contain the specified handler.
64   template <typename Executor, typename Handler>
overlapped_ptr(const Executor & ex,BOOST_ASIO_MOVE_ARG (Handler)handler,typename constraint<execution::is_executor<Executor>::value||is_executor<Executor>::value>::type=0)65   explicit overlapped_ptr(const Executor& ex,
66       BOOST_ASIO_MOVE_ARG(Handler) handler,
67       typename constraint<
68         execution::is_executor<Executor>::value
69           || is_executor<Executor>::value
70       >::type = 0)
71     : impl_(ex, BOOST_ASIO_MOVE_CAST(Handler)(handler))
72   {
73   }
74 
75   /// Destructor automatically frees the OVERLAPPED object unless released.
~overlapped_ptr()76   ~overlapped_ptr()
77   {
78   }
79 
80   /// Reset to empty.
reset()81   void reset()
82   {
83     impl_.reset();
84   }
85 
86   /// Reset to contain the specified handler, freeing any current OVERLAPPED
87   /// object.
88   template <typename ExecutionContext, typename Handler>
reset(ExecutionContext & context,BOOST_ASIO_MOVE_ARG (Handler)handler,typename constraint<is_convertible<ExecutionContext &,execution_context &>::value>::type=0)89   void reset(ExecutionContext& context, BOOST_ASIO_MOVE_ARG(Handler) handler,
90       typename constraint<
91         is_convertible<ExecutionContext&, execution_context&>::value
92       >::type = 0)
93   {
94     impl_.reset(context.get_executor(), BOOST_ASIO_MOVE_CAST(Handler)(handler));
95   }
96 
97   /// Reset to contain the specified handler, freeing any current OVERLAPPED
98   /// object.
99   template <typename Executor, typename Handler>
reset(const Executor & ex,BOOST_ASIO_MOVE_ARG (Handler)handler,typename constraint<execution::is_executor<Executor>::value||is_executor<Executor>::value>::type=0)100   void reset(const Executor& ex, BOOST_ASIO_MOVE_ARG(Handler) handler,
101       typename constraint<
102         execution::is_executor<Executor>::value
103           || is_executor<Executor>::value
104       >::type = 0)
105   {
106     impl_.reset(ex, BOOST_ASIO_MOVE_CAST(Handler)(handler));
107   }
108 
109   /// Get the contained OVERLAPPED object.
get()110   OVERLAPPED* get()
111   {
112     return impl_.get();
113   }
114 
115   /// Get the contained OVERLAPPED object.
get() const116   const OVERLAPPED* get() const
117   {
118     return impl_.get();
119   }
120 
121   /// Release ownership of the OVERLAPPED object.
release()122   OVERLAPPED* release()
123   {
124     return impl_.release();
125   }
126 
127   /// Post completion notification for overlapped operation. Releases ownership.
complete(const boost::system::error_code & ec,std::size_t bytes_transferred)128   void complete(const boost::system::error_code& ec,
129       std::size_t bytes_transferred)
130   {
131     impl_.complete(ec, bytes_transferred);
132   }
133 
134 private:
135   detail::win_iocp_overlapped_ptr impl_;
136 };
137 
138 } // namespace windows
139 } // namespace asio
140 } // namespace boost
141 
142 #include <boost/asio/detail/pop_options.hpp>
143 
144 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
145        //   || defined(GENERATING_DOCUMENTATION)
146 
147 #endif // BOOST_ASIO_WINDOWS_OVERLAPPED_PTR_HPP
148