Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/asio/detail/win_iocp_io_context.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // detail/win_iocp_io_context.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
0012 #define BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_HAS_IOCP)
0021 
0022 #include <boost/asio/detail/limits.hpp>
0023 #include <boost/asio/detail/mutex.hpp>
0024 #include <boost/asio/detail/op_queue.hpp>
0025 #include <boost/asio/detail/scoped_ptr.hpp>
0026 #include <boost/asio/detail/socket_types.hpp>
0027 #include <boost/asio/detail/thread.hpp>
0028 #include <boost/asio/detail/thread_context.hpp>
0029 #include <boost/asio/detail/timer_queue_base.hpp>
0030 #include <boost/asio/detail/timer_queue_set.hpp>
0031 #include <boost/asio/detail/wait_op.hpp>
0032 #include <boost/asio/detail/win_iocp_operation.hpp>
0033 #include <boost/asio/detail/win_iocp_thread_info.hpp>
0034 #include <boost/asio/execution_context.hpp>
0035 
0036 #include <boost/asio/detail/push_options.hpp>
0037 
0038 namespace boost {
0039 namespace asio {
0040 namespace detail {
0041 
0042 class wait_op;
0043 
0044 class win_iocp_io_context
0045   : public execution_context_service_base<win_iocp_io_context>,
0046     public thread_context
0047 {
0048 public:
0049   // Constructor.
0050   BOOST_ASIO_DECL win_iocp_io_context(
0051       boost::asio::execution_context& ctx, bool own_thread = true);
0052 
0053   // Destructor.
0054   BOOST_ASIO_DECL ~win_iocp_io_context();
0055 
0056   // Destroy all user-defined handler objects owned by the service.
0057   BOOST_ASIO_DECL void shutdown();
0058 
0059   // Initialise the task. Nothing to do here.
0060   void init_task()
0061   {
0062   }
0063 
0064   // Register a handle with the IO completion port.
0065   BOOST_ASIO_DECL boost::system::error_code register_handle(
0066       HANDLE handle, boost::system::error_code& ec);
0067 
0068   // Run the event loop until stopped or no more work.
0069   BOOST_ASIO_DECL size_t run(boost::system::error_code& ec);
0070 
0071   // Run until stopped or one operation is performed.
0072   BOOST_ASIO_DECL size_t run_one(boost::system::error_code& ec);
0073 
0074   // Run until timeout, interrupted, or one operation is performed.
0075   BOOST_ASIO_DECL size_t wait_one(long usec, boost::system::error_code& ec);
0076 
0077   // Poll for operations without blocking.
0078   BOOST_ASIO_DECL size_t poll(boost::system::error_code& ec);
0079 
0080   // Poll for one operation without blocking.
0081   BOOST_ASIO_DECL size_t poll_one(boost::system::error_code& ec);
0082 
0083   // Stop the event processing loop.
0084   BOOST_ASIO_DECL void stop();
0085 
0086   // Determine whether the io_context is stopped.
0087   bool stopped() const
0088   {
0089     return ::InterlockedExchangeAdd(&stopped_, 0) != 0;
0090   }
0091 
0092   // Restart in preparation for a subsequent run invocation.
0093   void restart()
0094   {
0095     ::InterlockedExchange(&stopped_, 0);
0096   }
0097 
0098   // Notify that some work has started.
0099   void work_started()
0100   {
0101     ::InterlockedIncrement(&outstanding_work_);
0102   }
0103 
0104   // Notify that some work has finished.
0105   void work_finished()
0106   {
0107     if (::InterlockedDecrement(&outstanding_work_) == 0)
0108       stop();
0109   }
0110 
0111   // Return whether a handler can be dispatched immediately.
0112   BOOST_ASIO_DECL bool can_dispatch();
0113 
0114   /// Capture the current exception so it can be rethrown from a run function.
0115   BOOST_ASIO_DECL void capture_current_exception();
0116 
0117   // Request invocation of the given operation and return immediately. Assumes
0118   // that work_started() has not yet been called for the operation.
0119   void post_immediate_completion(win_iocp_operation* op, bool)
0120   {
0121     work_started();
0122     post_deferred_completion(op);
0123   }
0124 
0125   // Request invocation of the given operation and return immediately. Assumes
0126   // that work_started() was previously called for the operation.
0127   BOOST_ASIO_DECL void post_deferred_completion(win_iocp_operation* op);
0128 
0129   // Request invocation of the given operation and return immediately. Assumes
0130   // that work_started() was previously called for the operations.
0131   BOOST_ASIO_DECL void post_deferred_completions(
0132       op_queue<win_iocp_operation>& ops);
0133 
0134   // Request invocation of the given operation using the thread-private queue
0135   // and return immediately. Assumes that work_started() has not yet been
0136   // called for the operation.
0137   void post_private_immediate_completion(win_iocp_operation* op)
0138   {
0139     post_immediate_completion(op, false);
0140   }
0141 
0142   // Request invocation of the given operation using the thread-private queue
0143   // and return immediately. Assumes that work_started() was previously called
0144   // for the operation.
0145   void post_private_deferred_completion(win_iocp_operation* op)
0146   {
0147     post_deferred_completion(op);
0148   }
0149 
0150   // Enqueue the given operation following a failed attempt to dispatch the
0151   // operation for immediate invocation.
0152   void do_dispatch(operation* op)
0153   {
0154     post_immediate_completion(op, false);
0155   }
0156 
0157   // Process unfinished operations as part of a shutdown operation. Assumes
0158   // that work_started() was previously called for the operations.
0159   BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
0160 
0161   // Called after starting an overlapped I/O operation that did not complete
0162   // immediately. The caller must have already called work_started() prior to
0163   // starting the operation.
0164   BOOST_ASIO_DECL void on_pending(win_iocp_operation* op);
0165 
0166   // Called after starting an overlapped I/O operation that completed
0167   // immediately. The caller must have already called work_started() prior to
0168   // starting the operation.
0169   BOOST_ASIO_DECL void on_completion(win_iocp_operation* op,
0170       DWORD last_error = 0, DWORD bytes_transferred = 0);
0171 
0172   // Called after starting an overlapped I/O operation that completed
0173   // immediately. The caller must have already called work_started() prior to
0174   // starting the operation.
0175   BOOST_ASIO_DECL void on_completion(win_iocp_operation* op,
0176       const boost::system::error_code& ec, DWORD bytes_transferred = 0);
0177 
0178   // Add a new timer queue to the service.
0179   template <typename Time_Traits>
0180   void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
0181 
0182   // Remove a timer queue from the service.
0183   template <typename Time_Traits>
0184   void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
0185 
0186   // Schedule a new operation in the given timer queue to expire at the
0187   // specified absolute time.
0188   template <typename Time_Traits>
0189   void schedule_timer(timer_queue<Time_Traits>& queue,
0190       const typename Time_Traits::time_type& time,
0191       typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
0192 
0193   // Cancel the timer associated with the given token. Returns the number of
0194   // handlers that have been posted or dispatched.
0195   template <typename Time_Traits>
0196   std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
0197       typename timer_queue<Time_Traits>::per_timer_data& timer,
0198       std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
0199 
0200   // Cancel the timer operations associated with the given key.
0201   template <typename Time_Traits>
0202   void cancel_timer_by_key(timer_queue<Time_Traits>& queue,
0203       typename timer_queue<Time_Traits>::per_timer_data* timer,
0204       void* cancellation_key);
0205 
0206   // Move the timer operations associated with the given timer.
0207   template <typename Time_Traits>
0208   void move_timer(timer_queue<Time_Traits>& queue,
0209       typename timer_queue<Time_Traits>::per_timer_data& to,
0210       typename timer_queue<Time_Traits>::per_timer_data& from);
0211 
0212 private:
0213 #if defined(WINVER) && (WINVER < 0x0500)
0214   typedef DWORD dword_ptr_t;
0215   typedef ULONG ulong_ptr_t;
0216 #else // defined(WINVER) && (WINVER < 0x0500)
0217   typedef DWORD_PTR dword_ptr_t;
0218   typedef ULONG_PTR ulong_ptr_t;
0219 #endif // defined(WINVER) && (WINVER < 0x0500)
0220 
0221   // Dequeues at most one operation from the I/O completion port, and then
0222   // executes it. Returns the number of operations that were dequeued (i.e.
0223   // either 0 or 1).
0224   BOOST_ASIO_DECL size_t do_one(DWORD msec,
0225       win_iocp_thread_info& this_thread, boost::system::error_code& ec);
0226 
0227   // Helper to calculate the GetQueuedCompletionStatus timeout.
0228   BOOST_ASIO_DECL static DWORD get_gqcs_timeout();
0229 
0230   // Helper function to add a new timer queue.
0231   BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
0232 
0233   // Helper function to remove a timer queue.
0234   BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
0235 
0236   // Called to recalculate and update the timeout.
0237   BOOST_ASIO_DECL void update_timeout();
0238 
0239   // Helper class to call work_finished() on block exit.
0240   struct work_finished_on_block_exit;
0241 
0242   // Helper class for managing a HANDLE.
0243   struct auto_handle
0244   {
0245     HANDLE handle;
0246     auto_handle() : handle(0) {}
0247     ~auto_handle() { if (handle) ::CloseHandle(handle); }
0248   };
0249 
0250   // The IO completion port used for queueing operations.
0251   auto_handle iocp_;
0252 
0253   // The count of unfinished work.
0254   long outstanding_work_;
0255 
0256   // Flag to indicate whether the event loop has been stopped.
0257   mutable long stopped_;
0258 
0259   // Flag to indicate whether there is an in-flight stop event. Every event
0260   // posted using PostQueuedCompletionStatus consumes non-paged pool, so to
0261   // avoid exhausting this resource we limit the number of outstanding events.
0262   long stop_event_posted_;
0263 
0264   // Flag to indicate whether the service has been shut down.
0265   long shutdown_;
0266 
0267   enum
0268   {
0269 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
0270     // Timeout to use with GetQueuedCompletionStatus on older versions of
0271     // Windows. Some versions of windows have a "bug" where a call to
0272     // GetQueuedCompletionStatus can appear stuck even though there are events
0273     // waiting on the queue. Using a timeout helps to work around the issue.
0274     default_gqcs_timeout = 500,
0275 #endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)
0276 
0277     // Maximum waitable timer timeout, in milliseconds.
0278     max_timeout_msec = 5 * 60 * 1000,
0279 
0280     // Maximum waitable timer timeout, in microseconds.
0281     max_timeout_usec = max_timeout_msec * 1000,
0282 
0283     // Completion key value used to wake up a thread to dispatch timers or
0284     // completed operations.
0285     wake_for_dispatch = 1,
0286 
0287     // Completion key value to indicate that an operation has posted with the
0288     // original last_error and bytes_transferred values stored in the fields of
0289     // the OVERLAPPED structure.
0290     overlapped_contains_result = 2
0291   };
0292 
0293   // Timeout to use with GetQueuedCompletionStatus.
0294   const DWORD gqcs_timeout_;
0295 
0296   // Helper class to run the scheduler in its own thread.
0297   struct thread_function;
0298   friend struct thread_function;
0299 
0300   // Function object for processing timeouts in a background thread.
0301   struct timer_thread_function;
0302   friend struct timer_thread_function;
0303 
0304   // Background thread used for processing timeouts.
0305   scoped_ptr<thread> timer_thread_;
0306 
0307   // A waitable timer object used for waiting for timeouts.
0308   auto_handle waitable_timer_;
0309 
0310   // Non-zero if timers or completed operations need to be dispatched.
0311   long dispatch_required_;
0312 
0313   // Mutex for protecting access to the timer queues and completed operations.
0314   mutex dispatch_mutex_;
0315 
0316   // The timer queues.
0317   timer_queue_set timer_queues_;
0318 
0319   // The operations that are ready to dispatch.
0320   op_queue<win_iocp_operation> completed_ops_;
0321 
0322   // The concurrency hint used to initialise the io_context.
0323   const int concurrency_hint_;
0324 
0325   // The thread that is running the io_context.
0326   scoped_ptr<thread> thread_;
0327 };
0328 
0329 } // namespace detail
0330 } // namespace asio
0331 } // namespace boost
0332 
0333 #include <boost/asio/detail/pop_options.hpp>
0334 
0335 #include <boost/asio/detail/impl/win_iocp_io_context.hpp>
0336 #if defined(BOOST_ASIO_HEADER_ONLY)
0337 # include <boost/asio/detail/impl/win_iocp_io_context.ipp>
0338 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0339 
0340 #endif // defined(BOOST_ASIO_HAS_IOCP)
0341 
0342 #endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP