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