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