Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:03

0001 //
0002 // windows/basic_object_handle.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 // Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 
0012 #ifndef BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
0013 #define BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
0014 
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0018 
0019 #include <boost/asio/detail/config.hpp>
0020 
0021 #if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
0022   || defined(GENERATING_DOCUMENTATION)
0023 
0024 #include <utility>
0025 #include <boost/asio/any_io_executor.hpp>
0026 #include <boost/asio/async_result.hpp>
0027 #include <boost/asio/detail/io_object_impl.hpp>
0028 #include <boost/asio/detail/throw_error.hpp>
0029 #include <boost/asio/detail/win_object_handle_service.hpp>
0030 #include <boost/asio/error.hpp>
0031 #include <boost/asio/execution_context.hpp>
0032 
0033 #include <boost/asio/detail/push_options.hpp>
0034 
0035 namespace boost {
0036 namespace asio {
0037 namespace windows {
0038 
0039 /// Provides object-oriented handle functionality.
0040 /**
0041  * The windows::basic_object_handle class provides asynchronous and blocking
0042  * object-oriented handle functionality.
0043  *
0044  * @par Thread Safety
0045  * @e Distinct @e objects: Safe.@n
0046  * @e Shared @e objects: Unsafe.
0047  */
0048 template <typename Executor = any_io_executor>
0049 class basic_object_handle
0050 {
0051 private:
0052   class initiate_async_wait;
0053 
0054 public:
0055   /// The type of the executor associated with the object.
0056   typedef Executor executor_type;
0057 
0058   /// Rebinds the handle type to another executor.
0059   template <typename Executor1>
0060   struct rebind_executor
0061   {
0062     /// The handle type when rebound to the specified executor.
0063     typedef basic_object_handle<Executor1> other;
0064   };
0065 
0066   /// The native representation of a handle.
0067 #if defined(GENERATING_DOCUMENTATION)
0068   typedef implementation_defined native_handle_type;
0069 #else
0070   typedef boost::asio::detail::win_object_handle_service::native_handle_type
0071     native_handle_type;
0072 #endif
0073 
0074   /// An object handle is always the lowest layer.
0075   typedef basic_object_handle lowest_layer_type;
0076 
0077   /// Construct an object handle without opening it.
0078   /**
0079    * This constructor creates an object handle without opening it.
0080    *
0081    * @param ex The I/O executor that the object handle will use, by default, to
0082    * dispatch handlers for any asynchronous operations performed on the
0083    * object handle.
0084    */
0085   explicit basic_object_handle(const executor_type& ex)
0086     : impl_(0, ex)
0087   {
0088   }
0089 
0090   /// Construct an object handle without opening it.
0091   /**
0092    * This constructor creates an object handle without opening it.
0093    *
0094    * @param context An execution context which provides the I/O executor that
0095    * the object handle will use, by default, to dispatch handlers for any
0096    * asynchronous operations performed on the object handle.
0097    */
0098   template <typename ExecutionContext>
0099   explicit basic_object_handle(ExecutionContext& context,
0100       constraint_t<
0101         is_convertible<ExecutionContext&, execution_context&>::value,
0102         defaulted_constraint
0103       > = defaulted_constraint())
0104     : impl_(0, 0, context)
0105   {
0106   }
0107 
0108   /// Construct an object handle on an existing native handle.
0109   /**
0110    * This constructor creates an object handle object to hold an existing native
0111    * handle.
0112    *
0113    * @param ex The I/O executor that the object handle will use, by default, to
0114    * dispatch handlers for any asynchronous operations performed on the
0115    * object handle.
0116    *
0117    * @param native_handle The new underlying handle implementation.
0118    *
0119    * @throws boost::system::system_error Thrown on failure.
0120    */
0121   basic_object_handle(const executor_type& ex,
0122       const native_handle_type& native_handle)
0123     : impl_(0, ex)
0124   {
0125     boost::system::error_code ec;
0126     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
0127     boost::asio::detail::throw_error(ec, "assign");
0128   }
0129 
0130   /// Construct an object handle on an existing native handle.
0131   /**
0132    * This constructor creates an object handle object to hold an existing native
0133    * handle.
0134    *
0135    * @param context An execution context which provides the I/O executor that
0136    * the object handle will use, by default, to dispatch handlers for any
0137    * asynchronous operations performed on the object handle.
0138    *
0139    * @param native_handle The new underlying handle implementation.
0140    *
0141    * @throws boost::system::system_error Thrown on failure.
0142    */
0143   template <typename ExecutionContext>
0144   basic_object_handle(ExecutionContext& context,
0145       const native_handle_type& native_handle,
0146       constraint_t<
0147         is_convertible<ExecutionContext&, execution_context&>::value
0148       > = 0)
0149     : impl_(0, 0, context)
0150   {
0151     boost::system::error_code ec;
0152     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
0153     boost::asio::detail::throw_error(ec, "assign");
0154   }
0155 
0156   /// Move-construct an object handle from another.
0157   /**
0158    * This constructor moves an object handle from one object to another.
0159    *
0160    * @param other The other object handle object from which the move will
0161    * occur.
0162    *
0163    * @note Following the move, the moved-from object is in the same state as if
0164    * constructed using the @c basic_object_handle(const executor_type&)
0165    * constructor.
0166    */
0167   basic_object_handle(basic_object_handle&& other)
0168     : impl_(std::move(other.impl_))
0169   {
0170   }
0171 
0172   /// Move-assign an object handle from another.
0173   /**
0174    * This assignment operator moves an object handle from one object to another.
0175    *
0176    * @param other The other object handle object from which the move will
0177    * occur.
0178    *
0179    * @note Following the move, the moved-from object is in the same state as if
0180    * constructed using the @c basic_object_handle(const executor_type&)
0181    * constructor.
0182    */
0183   basic_object_handle& operator=(basic_object_handle&& other)
0184   {
0185     impl_ = std::move(other.impl_);
0186     return *this;
0187   }
0188 
0189   // All handles have access to each other's implementations.
0190   template <typename Executor1>
0191   friend class basic_object_handle;
0192 
0193   /// Move-construct an object handle from a handle of another executor type.
0194   /**
0195    * This constructor moves an object handle from one object to another.
0196    *
0197    * @param other The other object handle object from which the move will
0198    * occur.
0199    *
0200    * @note Following the move, the moved-from object is in the same state as if
0201    * constructed using the @c basic_object_handle(const executor_type&)
0202    * constructor.
0203    */
0204   template<typename Executor1>
0205   basic_object_handle(basic_object_handle<Executor1>&& other,
0206       constraint_t<
0207         is_convertible<Executor1, Executor>::value,
0208         defaulted_constraint
0209       > = defaulted_constraint())
0210     : impl_(std::move(other.impl_))
0211   {
0212   }
0213 
0214   /// Move-assign an object handle from a handle of another executor type.
0215   /**
0216    * This assignment operator moves an object handle from one object to another.
0217    *
0218    * @param other The other object handle object from which the move will
0219    * occur.
0220    *
0221    * @note Following the move, the moved-from object is in the same state as if
0222    * constructed using the @c basic_object_handle(const executor_type&)
0223    * constructor.
0224    */
0225   template<typename Executor1>
0226   constraint_t<
0227     is_convertible<Executor1, Executor>::value,
0228     basic_object_handle&
0229   > operator=(basic_object_handle<Executor1>&& other)
0230   {
0231     impl_ = std::move(other.impl_);
0232     return *this;
0233   }
0234 
0235   /// Get the executor associated with the object.
0236   const executor_type& get_executor() noexcept
0237   {
0238     return impl_.get_executor();
0239   }
0240 
0241   /// Get a reference to the lowest layer.
0242   /**
0243    * This function returns a reference to the lowest layer in a stack of
0244    * layers. Since an object handle cannot contain any further layers, it simply
0245    * returns a reference to itself.
0246    *
0247    * @return A reference to the lowest layer in the stack of layers. Ownership
0248    * is not transferred to the caller.
0249    */
0250   lowest_layer_type& lowest_layer()
0251   {
0252     return *this;
0253   }
0254 
0255   /// Get a const reference to the lowest layer.
0256   /**
0257    * This function returns a const reference to the lowest layer in a stack of
0258    * layers. Since an object handle cannot contain any further layers, it simply
0259    * returns a reference to itself.
0260    *
0261    * @return A const reference to the lowest layer in the stack of layers.
0262    * Ownership is not transferred to the caller.
0263    */
0264   const lowest_layer_type& lowest_layer() const
0265   {
0266     return *this;
0267   }
0268 
0269   /// Assign an existing native handle to the handle.
0270   /*
0271    * This function opens the handle to hold an existing native handle.
0272    *
0273    * @param handle A native handle.
0274    *
0275    * @throws boost::system::system_error Thrown on failure.
0276    */
0277   void assign(const native_handle_type& handle)
0278   {
0279     boost::system::error_code ec;
0280     impl_.get_service().assign(impl_.get_implementation(), handle, ec);
0281     boost::asio::detail::throw_error(ec, "assign");
0282   }
0283 
0284   /// Assign an existing native handle to the handle.
0285   /*
0286    * This function opens the handle to hold an existing native handle.
0287    *
0288    * @param handle A native handle.
0289    *
0290    * @param ec Set to indicate what error occurred, if any.
0291    */
0292   BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
0293       boost::system::error_code& ec)
0294   {
0295     impl_.get_service().assign(impl_.get_implementation(), handle, ec);
0296     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0297   }
0298 
0299   /// Determine whether the handle is open.
0300   bool is_open() const
0301   {
0302     return impl_.get_service().is_open(impl_.get_implementation());
0303   }
0304 
0305   /// Close the handle.
0306   /**
0307    * This function is used to close the handle. Any asynchronous read or write
0308    * operations will be cancelled immediately, and will complete with the
0309    * boost::asio::error::operation_aborted error.
0310    *
0311    * @throws boost::system::system_error Thrown on failure.
0312    */
0313   void close()
0314   {
0315     boost::system::error_code ec;
0316     impl_.get_service().close(impl_.get_implementation(), ec);
0317     boost::asio::detail::throw_error(ec, "close");
0318   }
0319 
0320   /// Close the handle.
0321   /**
0322    * This function is used to close the handle. Any asynchronous read or write
0323    * operations will be cancelled immediately, and will complete with the
0324    * boost::asio::error::operation_aborted error.
0325    *
0326    * @param ec Set to indicate what error occurred, if any.
0327    */
0328   BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
0329   {
0330     impl_.get_service().close(impl_.get_implementation(), ec);
0331     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0332   }
0333 
0334   /// Get the native handle representation.
0335   /**
0336    * This function may be used to obtain the underlying representation of the
0337    * handle. This is intended to allow access to native handle functionality
0338    * that is not otherwise provided.
0339    */
0340   native_handle_type native_handle()
0341   {
0342     return impl_.get_service().native_handle(impl_.get_implementation());
0343   }
0344 
0345   /// Cancel all asynchronous operations associated with the handle.
0346   /**
0347    * This function causes all outstanding asynchronous read or write operations
0348    * to finish immediately, and the handlers for cancelled operations will be
0349    * passed the boost::asio::error::operation_aborted error.
0350    *
0351    * @throws boost::system::system_error Thrown on failure.
0352    */
0353   void cancel()
0354   {
0355     boost::system::error_code ec;
0356     impl_.get_service().cancel(impl_.get_implementation(), ec);
0357     boost::asio::detail::throw_error(ec, "cancel");
0358   }
0359 
0360   /// Cancel all asynchronous operations associated with the handle.
0361   /**
0362    * This function causes all outstanding asynchronous read or write operations
0363    * to finish immediately, and the handlers for cancelled operations will be
0364    * passed the boost::asio::error::operation_aborted error.
0365    *
0366    * @param ec Set to indicate what error occurred, if any.
0367    */
0368   BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
0369   {
0370     impl_.get_service().cancel(impl_.get_implementation(), ec);
0371     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0372   }
0373 
0374   /// Perform a blocking wait on the object handle.
0375   /**
0376    * This function is used to wait for the object handle to be set to the
0377    * signalled state. This function blocks and does not return until the object
0378    * handle has been set to the signalled state.
0379    *
0380    * @throws boost::system::system_error Thrown on failure.
0381    */
0382   void wait()
0383   {
0384     boost::system::error_code ec;
0385     impl_.get_service().wait(impl_.get_implementation(), ec);
0386     boost::asio::detail::throw_error(ec, "wait");
0387   }
0388 
0389   /// Perform a blocking wait on the object handle.
0390   /**
0391    * This function is used to wait for the object handle to be set to the
0392    * signalled state. This function blocks and does not return until the object
0393    * handle has been set to the signalled state.
0394    *
0395    * @param ec Set to indicate what error occurred, if any.
0396    */
0397   void wait(boost::system::error_code& ec)
0398   {
0399     impl_.get_service().wait(impl_.get_implementation(), ec);
0400   }
0401 
0402   /// Start an asynchronous wait on the object handle.
0403   /**
0404    * This function is be used to initiate an asynchronous wait against the
0405    * object handle. It is an initiating function for an @ref
0406    * asynchronous_operation, and always returns immediately.
0407    *
0408    * @param token The @ref completion_token that will be used to produce a
0409    * completion handler, which will be called when the wait completes.
0410    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0411    * @ref yield_context, or a function object with the correct completion
0412    * signature. The function signature of the completion handler must be:
0413    * @code void handler(
0414    *   const boost::system::error_code& error // Result of operation.
0415    * ); @endcode
0416    * Regardless of whether the asynchronous operation completes immediately or
0417    * not, the completion handler will not be invoked from within this function.
0418    * On immediate completion, invocation of the handler will be performed in a
0419    * manner equivalent to using boost::asio::post().
0420    *
0421    * @par Completion Signature
0422    * @code void(boost::system::error_code) @endcode
0423    */
0424   template <
0425       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
0426         WaitToken = default_completion_token_t<executor_type>>
0427   auto async_wait(
0428       WaitToken&& token = default_completion_token_t<executor_type>())
0429     -> decltype(
0430       async_initiate<WaitToken, void (boost::system::error_code)>(
0431         declval<initiate_async_wait>(), token))
0432   {
0433     return async_initiate<WaitToken, void (boost::system::error_code)>(
0434         initiate_async_wait(this), token);
0435   }
0436 
0437 private:
0438   // Disallow copying and assignment.
0439   basic_object_handle(const basic_object_handle&) = delete;
0440   basic_object_handle& operator=(const basic_object_handle&) = delete;
0441 
0442   class initiate_async_wait
0443   {
0444   public:
0445     typedef Executor executor_type;
0446 
0447     explicit initiate_async_wait(basic_object_handle* self)
0448       : self_(self)
0449     {
0450     }
0451 
0452     const executor_type& get_executor() const noexcept
0453     {
0454       return self_->get_executor();
0455     }
0456 
0457     template <typename WaitHandler>
0458     void operator()(WaitHandler&& handler) const
0459     {
0460       // If you get an error on the following line it means that your handler
0461       // does not meet the documented type requirements for a WaitHandler.
0462       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
0463 
0464       detail::non_const_lvalue<WaitHandler> handler2(handler);
0465       self_->impl_.get_service().async_wait(
0466           self_->impl_.get_implementation(),
0467           handler2.value, self_->impl_.get_executor());
0468     }
0469 
0470   private:
0471     basic_object_handle* self_;
0472   };
0473 
0474   boost::asio::detail::io_object_impl<
0475     boost::asio::detail::win_object_handle_service, Executor> impl_;
0476 };
0477 
0478 } // namespace windows
0479 } // namespace asio
0480 } // namespace boost
0481 
0482 #include <boost/asio/detail/pop_options.hpp>
0483 
0484 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
0485        //   || defined(GENERATING_DOCUMENTATION)
0486 
0487 #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP