1//
2// detail/executor_function.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 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_EXECUTOR_FUNCTION_HPP
12#define BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_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#include <boost/asio/detail/handler_alloc_helpers.hpp>
20#include <boost/asio/detail/memory.hpp>
21
22#include <boost/asio/detail/push_options.hpp>
23
24namespace boost {
25namespace asio {
26namespace detail {
27
28// Lightweight, move-only function object wrapper.
29class executor_function
30{
31public:
32 template <typename F, typename Alloc>
33 explicit executor_function(F f, const Alloc& a)
34 {
35 // Allocate and construct an object to wrap the function.
36 typedef impl<F, Alloc> impl_type;
37 typename impl_type::ptr p = {
38 detail::addressof(a), impl_type::ptr::allocate(a), 0 };
39 impl_ = new (p.v) impl_type(static_cast<F&&>(f), a);
40 p.v = 0;
41 }
42
43 executor_function(executor_function&& other) noexcept
44 : impl_(other.impl_)
45 {
46 other.impl_ = 0;
47 }
48
49 ~executor_function()
50 {
51 if (impl_)
52 impl_->complete_(impl_, false);
53 }
54
55 void operator()()
56 {
57 if (impl_)
58 {
59 impl_base* i = impl_;
60 impl_ = 0;
61 i->complete_(i, true);
62 }
63 }
64
65private:
66 // Base class for polymorphic function implementations.
67 struct impl_base
68 {
69 void (*complete_)(impl_base*, bool);
70 };
71
72 // Polymorphic function implementation.
73 template <typename Function, typename Alloc>
74 struct impl : impl_base
75 {
76 BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
77 thread_info_base::executor_function_tag, impl);
78
79 template <typename F>
80 impl(F&& f, const Alloc& a)
81 : function_(static_cast<F&&>(f)),
82 allocator_(a)
83 {
84 complete_ = &executor_function::complete<Function, Alloc>;
85 }
86
87 Function function_;
88 Alloc allocator_;
89 };
90
91 // Helper to complete function invocation.
92 template <typename Function, typename Alloc>
93 static void complete(impl_base* base, bool call)
94 {
95 // Take ownership of the function object.
96 impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));
97 Alloc allocator(i->allocator_);
98 typename impl<Function, Alloc>::ptr p = {
99 detail::addressof(allocator), i, i };
100
101 // Make a copy of the function so that the memory can be deallocated before
102 // the upcall is made. Even if we're not about to make an upcall, a
103 // sub-object of the function may be the true owner of the memory
104 // associated with the function. Consequently, a local copy of the function
105 // is required to ensure that any owning sub-object remains valid until
106 // after we have deallocated the memory here.
107 Function function(static_cast<Function&&>(i->function_));
108 p.reset();
109
110 // Make the upcall if required.
111 if (call)
112 {
113 static_cast<Function&&>(function)();
114 }
115 }
116
117 impl_base* impl_;
118};
119
120// Lightweight, non-owning, copyable function object wrapper.
121class executor_function_view
122{
123public:
124 template <typename F>
125 explicit executor_function_view(F& f) noexcept
126 : complete_(&executor_function_view::complete<F>),
127 function_(&f)
128 {
129 }
130
131 void operator()()
132 {
133 complete_(function_);
134 }
135
136private:
137 // Helper to complete function invocation.
138 template <typename F>
139 static void complete(void* f)
140 {
141 (*static_cast<F*>(f))();
142 }
143
144 void (*complete_)(void*);
145 void* function_;
146};
147
148} // namespace detail
149} // namespace asio
150} // namespace boost
151
152#include <boost/asio/detail/pop_options.hpp>
153
154#endif // BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
155

source code of boost/libs/asio/include/boost/asio/detail/executor_function.hpp