1 //
2 // detail/handler_tracking.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_DETAIL_HANDLER_TRACKING_HPP
12 #define BOOST_ASIO_DETAIL_HANDLER_TRACKING_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 namespace boost {
21 namespace asio {
22 
23 class execution_context;
24 
25 } // namespace asio
26 } // namespace boost
27 
28 #if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
29 # include BOOST_ASIO_CUSTOM_HANDLER_TRACKING
30 #elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
31 # include <boost/system/error_code.hpp>
32 # include <boost/asio/detail/cstdint.hpp>
33 # include <boost/asio/detail/static_mutex.hpp>
34 # include <boost/asio/detail/tss_ptr.hpp>
35 #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
36 
37 #include <boost/asio/detail/push_options.hpp>
38 
39 namespace boost {
40 namespace asio {
41 namespace detail {
42 
43 #if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
44 
45 // The user-specified header must define the following macros:
46 // - BOOST_ASIO_INHERIT_TRACKED_HANDLER
47 // - BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
48 // - BOOST_ASIO_HANDLER_TRACKING_INIT
49 // - BOOST_ASIO_HANDLER_CREATION(args)
50 // - BOOST_ASIO_HANDLER_COMPLETION(args)
51 // - BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args)
52 // - BOOST_ASIO_HANDLER_INVOCATION_END
53 // - BOOST_ASIO_HANDLER_OPERATION(args)
54 // - BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args)
55 // - BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args)
56 // - BOOST_ASIO_HANDLER_REACTOR_READ_EVENT
57 // - BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT
58 // - BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT
59 // - BOOST_ASIO_HANDLER_REACTOR_EVENTS(args)
60 // - BOOST_ASIO_HANDLER_REACTOR_OPERATION(args)
61 
62 # if !defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
63 #  define BOOST_ASIO_ENABLE_HANDLER_TRACKING 1
64 # endif /// !defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
65 
66 #elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
67 
68 class handler_tracking
69 {
70 public:
71   class completion;
72 
73   // Base class for objects containing tracked handlers.
74   class tracked_handler
75   {
76   private:
77     // Only the handler_tracking class will have access to the id.
78     friend class handler_tracking;
79     friend class completion;
80     uint64_t id_;
81 
82   protected:
83     // Constructor initialises with no id.
84     tracked_handler() : id_(0) {}
85 
86     // Prevent deletion through this type.
87     ~tracked_handler() {}
88   };
89 
90   // Initialise the tracking system.
91   BOOST_ASIO_DECL static void init();
92 
93   class location
94   {
95   public:
96     // Constructor adds a location to the stack.
97     BOOST_ASIO_DECL explicit location(const char* file,
98         int line, const char* func);
99 
100     // Destructor removes a location from the stack.
101     BOOST_ASIO_DECL ~location();
102 
103   private:
104     // Disallow copying and assignment.
105     location(const location&) BOOST_ASIO_DELETED;
106     location& operator=(const location&) BOOST_ASIO_DELETED;
107 
108     friend class handler_tracking;
109     const char* file_;
110     int line_;
111     const char* func_;
112     location* next_;
113   };
114 
115   // Record the creation of a tracked handler.
116   BOOST_ASIO_DECL static void creation(
117       execution_context& context, tracked_handler& h,
118       const char* object_type, void* object,
119       uintmax_t native_handle, const char* op_name);
120 
121   class completion
122   {
123   public:
124     // Constructor records that handler is to be invoked with no arguments.
125     BOOST_ASIO_DECL explicit completion(const tracked_handler& h);
126 
127     // Destructor records only when an exception is thrown from the handler, or
128     // if the memory is being freed without the handler having been invoked.
129     BOOST_ASIO_DECL ~completion();
130 
131     // Records that handler is to be invoked with no arguments.
132     BOOST_ASIO_DECL void invocation_begin();
133 
134     // Records that handler is to be invoked with one arguments.
135     BOOST_ASIO_DECL void invocation_begin(const boost::system::error_code& ec);
136 
137     // Constructor records that handler is to be invoked with two arguments.
138     BOOST_ASIO_DECL void invocation_begin(
139         const boost::system::error_code& ec, std::size_t bytes_transferred);
140 
141     // Constructor records that handler is to be invoked with two arguments.
142     BOOST_ASIO_DECL void invocation_begin(
143         const boost::system::error_code& ec, int signal_number);
144 
145     // Constructor records that handler is to be invoked with two arguments.
146     BOOST_ASIO_DECL void invocation_begin(
147         const boost::system::error_code& ec, const char* arg);
148 
149     // Record that handler invocation has ended.
150     BOOST_ASIO_DECL void invocation_end();
151 
152   private:
153     friend class handler_tracking;
154     uint64_t id_;
155     bool invoked_;
156     completion* next_;
157   };
158 
159   // Record an operation that is not directly associated with a handler.
160   BOOST_ASIO_DECL static void operation(execution_context& context,
161       const char* object_type, void* object,
162       uintmax_t native_handle, const char* op_name);
163 
164   // Record that a descriptor has been registered with the reactor.
165   BOOST_ASIO_DECL static void reactor_registration(execution_context& context,
166       uintmax_t native_handle, uintmax_t registration);
167 
168   // Record that a descriptor has been deregistered from the reactor.
169   BOOST_ASIO_DECL static void reactor_deregistration(execution_context& context,
170       uintmax_t native_handle, uintmax_t registration);
171 
172   // Record a reactor-based operation that is associated with a handler.
173   BOOST_ASIO_DECL static void reactor_events(execution_context& context,
174       uintmax_t registration, unsigned events);
175 
176   // Record a reactor-based operation that is associated with a handler.
177   BOOST_ASIO_DECL static void reactor_operation(
178       const tracked_handler& h, const char* op_name,
179       const boost::system::error_code& ec);
180 
181   // Record a reactor-based operation that is associated with a handler.
182   BOOST_ASIO_DECL static void reactor_operation(
183       const tracked_handler& h, const char* op_name,
184       const boost::system::error_code& ec, std::size_t bytes_transferred);
185 
186   // Write a line of output.
187   BOOST_ASIO_DECL static void write_line(const char* format, ...);
188 
189 private:
190   struct tracking_state;
191   BOOST_ASIO_DECL static tracking_state* get_state();
192 };
193 
194 # define BOOST_ASIO_INHERIT_TRACKED_HANDLER \
195   : public boost::asio::detail::handler_tracking::tracked_handler
196 
197 # define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER \
198   , public boost::asio::detail::handler_tracking::tracked_handler
199 
200 # define BOOST_ASIO_HANDLER_TRACKING_INIT \
201   boost::asio::detail::handler_tracking::init()
202 
203 # define BOOST_ASIO_HANDLER_LOCATION(args) \
204   boost::asio::detail::handler_tracking::location tracked_location args
205 
206 # define BOOST_ASIO_HANDLER_CREATION(args) \
207   boost::asio::detail::handler_tracking::creation args
208 
209 # define BOOST_ASIO_HANDLER_COMPLETION(args) \
210   boost::asio::detail::handler_tracking::completion tracked_completion args
211 
212 # define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) \
213   tracked_completion.invocation_begin args
214 
215 # define BOOST_ASIO_HANDLER_INVOCATION_END \
216   tracked_completion.invocation_end()
217 
218 # define BOOST_ASIO_HANDLER_OPERATION(args) \
219   boost::asio::detail::handler_tracking::operation args
220 
221 # define BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) \
222   boost::asio::detail::handler_tracking::reactor_registration args
223 
224 # define BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) \
225   boost::asio::detail::handler_tracking::reactor_deregistration args
226 
227 # define BOOST_ASIO_HANDLER_REACTOR_READ_EVENT 1
228 # define BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT 2
229 # define BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT 4
230 
231 # define BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) \
232   boost::asio::detail::handler_tracking::reactor_events args
233 
234 # define BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) \
235   boost::asio::detail::handler_tracking::reactor_operation args
236 
237 #else // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
238 
239 # define BOOST_ASIO_INHERIT_TRACKED_HANDLER
240 # define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
241 # define BOOST_ASIO_HANDLER_TRACKING_INIT (void)0
242 # define BOOST_ASIO_HANDLER_LOCATION(loc) (void)0
243 # define BOOST_ASIO_HANDLER_CREATION(args) (void)0
244 # define BOOST_ASIO_HANDLER_COMPLETION(args) (void)0
245 # define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0
246 # define BOOST_ASIO_HANDLER_INVOCATION_END (void)0
247 # define BOOST_ASIO_HANDLER_OPERATION(args) (void)0
248 # define BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) (void)0
249 # define BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) (void)0
250 # define BOOST_ASIO_HANDLER_REACTOR_READ_EVENT 0
251 # define BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT 0
252 # define BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT 0
253 # define BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) (void)0
254 # define BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) (void)0
255 
256 #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
257 
258 } // namespace detail
259 } // namespace asio
260 } // namespace boost
261 
262 #include <boost/asio/detail/pop_options.hpp>
263 
264 #if defined(BOOST_ASIO_HEADER_ONLY)
265 # include <boost/asio/detail/impl/handler_tracking.ipp>
266 #endif // defined(BOOST_ASIO_HEADER_ONLY)
267 
268 #endif // BOOST_ASIO_DETAIL_HANDLER_TRACKING_HPP
269