1 //
2 // detail/impl/strand_service.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_IMPL_STRAND_SERVICE_HPP
12 #define BOOST_ASIO_DETAIL_IMPL_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/completion_handler.hpp>
19 #include <boost/asio/detail/fenced_block.hpp>
20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
21 #include <boost/asio/detail/handler_invoke_helpers.hpp>
22 #include <boost/asio/detail/memory.hpp>
23 
24 #include <boost/asio/detail/push_options.hpp>
25 
26 namespace boost {
27 namespace asio {
28 namespace detail {
29 
strand_impl()30 inline strand_service::strand_impl::strand_impl()
31   : operation(&strand_service::do_complete),
32     locked_(false)
33 {
34 }
35 
36 template <typename Handler>
dispatch(strand_service::implementation_type & impl,Handler & handler)37 void strand_service::dispatch(strand_service::implementation_type& impl,
38     Handler& handler)
39 {
40   // If we are already in the strand then the handler can run immediately.
41   if (running_in_this_thread(impl))
42   {
43     fenced_block b(fenced_block::full);
44     boost_asio_handler_invoke_helpers::invoke(handler, handler);
45     return;
46   }
47 
48   // Allocate and construct an operation to wrap the handler.
49   typedef completion_handler<Handler, io_context::executor_type> op;
50   typename op::ptr p = { boost::asio::detail::addressof(handler),
51     op::ptr::allocate(handler), 0 };
52   p.p = new (p.v) op(handler, io_context_.get_executor());
53 
54   BOOST_ASIO_HANDLER_CREATION((this->context(),
55         *p.p, "strand", impl, 0, "dispatch"));
56 
57   operation* o = p.p;
58   p.v = p.p = 0;
59   do_dispatch(impl, o);
60 }
61 
62 // Request the io_context to invoke the given handler and return immediately.
63 template <typename Handler>
post(strand_service::implementation_type & impl,Handler & handler)64 void strand_service::post(strand_service::implementation_type& impl,
65     Handler& handler)
66 {
67   bool is_continuation =
68     boost_asio_handler_cont_helpers::is_continuation(handler);
69 
70   // Allocate and construct an operation to wrap the handler.
71   typedef completion_handler<Handler, io_context::executor_type> op;
72   typename op::ptr p = { boost::asio::detail::addressof(handler),
73     op::ptr::allocate(handler), 0 };
74   p.p = new (p.v) op(handler, io_context_.get_executor());
75 
76   BOOST_ASIO_HANDLER_CREATION((this->context(),
77         *p.p, "strand", impl, 0, "post"));
78 
79   do_post(impl, p.p, is_continuation);
80   p.v = p.p = 0;
81 }
82 
83 } // namespace detail
84 } // namespace asio
85 } // namespace boost
86 
87 #include <boost/asio/detail/pop_options.hpp>
88 
89 #endif // BOOST_ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
90