Clementine
strand_service.hpp
1 //
2 // detail/strand_service.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 ASIO_DETAIL_STRAND_SERVICE_HPP
12 #define ASIO_DETAIL_STRAND_SERVICE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 #include "asio/io_context.hpp"
20 #include "asio/detail/mutex.hpp"
21 #include "asio/detail/op_queue.hpp"
22 #include "asio/detail/operation.hpp"
23 #include "asio/detail/scoped_ptr.hpp"
24 
25 #include "asio/detail/push_options.hpp"
26 
27 namespace asio {
28 namespace detail {
29 
30 // Default service implementation for a strand.
32  : public asio::detail::service_base<strand_service>
33 {
34 private:
35  // Helper class to re-post the strand on exit.
36  struct on_do_complete_exit;
37 
38  // Helper class to re-post the strand on exit.
39  struct on_dispatch_exit;
40 
41 public:
42 
43  // The underlying implementation of a strand.
45  : public operation
46  {
47  public:
48  strand_impl();
49 
50  private:
51  // Only this service will have access to the internal values.
52  friend class strand_service;
53  friend struct on_do_complete_exit;
54  friend struct on_dispatch_exit;
55 
56  // Mutex to protect access to internal data.
57  asio::detail::mutex mutex_;
58 
59  // Indicates whether the strand is currently "locked" by a handler. This
60  // means that there is a handler upcall in progress, or that the strand
61  // itself has been scheduled in order to invoke some pending handlers.
62  bool locked_;
63 
64  // The handlers that are waiting on the strand but should not be run until
65  // after the next time the strand is scheduled. This queue must only be
66  // modified while the mutex is locked.
67  op_queue<operation> waiting_queue_;
68 
69  // The handlers that are ready to be run. Logically speaking, these are the
70  // handlers that hold the strand's lock. The ready queue is only modified
71  // from within the strand and so may be accessed without locking the mutex.
72  op_queue<operation> ready_queue_;
73  };
74 
76 
77  // Construct a new strand service for the specified io_context.
78  ASIO_DECL explicit strand_service(asio::io_context& io_context);
79 
80  // Destroy all user-defined handler objects owned by the service.
81  ASIO_DECL void shutdown();
82 
83  // Construct a new strand implementation.
84  ASIO_DECL void construct(implementation_type& impl);
85 
86  // Request the io_context to invoke the given handler.
87  template <typename Handler>
88  void dispatch(implementation_type& impl, Handler& handler);
89 
90  // Request the io_context to invoke the given handler and return immediately.
91  template <typename Handler>
92  void post(implementation_type& impl, Handler& handler);
93 
94  // Determine whether the strand is running in the current thread.
95  ASIO_DECL bool running_in_this_thread(
96  const implementation_type& impl) const;
97 
98 private:
99  // Helper function to dispatch a handler. Returns true if the handler should
100  // be dispatched immediately.
101  ASIO_DECL bool do_dispatch(implementation_type& impl, operation* op);
102 
103  // Helper fiunction to post a handler.
104  ASIO_DECL void do_post(implementation_type& impl,
105  operation* op, bool is_continuation);
106 
107  ASIO_DECL static void do_complete(void* owner,
108  operation* base, const asio::error_code& ec,
109  std::size_t bytes_transferred);
110 
111  // The io_context used to obtain an I/O executor.
112  io_context& io_context_;
113 
114  // The io_context implementation used to post completions.
115  io_context_impl& io_context_impl_;
116 
117  // Mutex to protect access to the array of implementations.
118  asio::detail::mutex mutex_;
119 
120  // Number of implementations shared between all strand objects.
121 #if defined(ASIO_STRAND_IMPLEMENTATIONS)
122  enum { num_implementations = ASIO_STRAND_IMPLEMENTATIONS };
123 #else // defined(ASIO_STRAND_IMPLEMENTATIONS)
124  enum { num_implementations = 193 };
125 #endif // defined(ASIO_STRAND_IMPLEMENTATIONS)
126 
127  // Pool of implementations.
128  scoped_ptr<strand_impl> implementations_[num_implementations];
129 
130  // Extra value used when hashing to prevent recycled memory locations from
131  // getting the same strand implementation.
132  std::size_t salt_;
133 };
134 
135 } // namespace detail
136 } // namespace asio
137 
138 #include "asio/detail/pop_options.hpp"
139 
140 #include "asio/detail/impl/strand_service.hpp"
141 #if defined(ASIO_HEADER_ONLY)
142 # include "asio/detail/impl/strand_service.ipp"
143 #endif // defined(ASIO_HEADER_ONLY)
144 
145 #endif // ASIO_DETAIL_STRAND_SERVICE_HPP
Definition: null_mutex.hpp:30
ASIO_DECL void shutdown()
Destroy all user-defined handler objects owned by the service.
Definition: strand_service.ipp:53
Definition: strand_service.hpp:44
Definition: io_context.hpp:1237
Definition: strand_service.hpp:36
Provides core I/O functionality.
Definition: io_context.hpp:211
Definition: chrono.h:284
Definition: strand_service.hpp:31
Definition: strand_service.ipp:27
Class to represent an error code value.
Definition: error_code.hpp:80
Definition: scoped_ptr.hpp:26
Definition: any_io_executor.hpp:28
Definition: scheduler.hpp:38