GCC Code Coverage Report


Directory: libs/beast2/
File: include/boost/beast2/server/any_lambda.hpp
Date: 2025-11-13 15:50:44
Exec Total Coverage
Lines: 0 32 0.0%
Functions: 0 9 0.0%
Branches: 0 6 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/beast2
8 //
9
10 #ifndef BOOST_BEAST2_SERVER_ANY_LAMBDA_HPP
11 #define BOOST_BEAST2_SERVER_ANY_LAMBDA_HPP
12
13 #include <boost/beast2/detail/config.hpp>
14
15 #include <cstddef>
16 #include <cstring>
17 #include <functional>
18 #include <new>
19 #include <stdexcept>
20 #include <type_traits>
21 #include <utility>
22
23 namespace boost {
24 namespace beast2 {
25
26 namespace detail {
27
28 struct A { void f(); int g() const; virtual void h(); };
29 struct B { virtual void f(); };
30 struct C : virtual B { void g(); };
31
32 constexpr std::size_t max_size(std::size_t a, std::size_t b) noexcept
33 {
34 return a > b ? a : b;
35 }
36
37 constexpr std::size_t max_sizeof_mfp() noexcept
38 {
39 return max_size(
40 max_size(
41 max_size(sizeof(void (A::*)()), sizeof(int (A::*)() const)),
42 sizeof(void (B::*)())
43 ),
44 sizeof(void (C::*)())
45 );
46 }
47
48 } // detail
49
50 template<class Signature>
51 struct any_lambda; // primary template left undefined
52
53 template<class R, class... Args>
54 struct any_lambda<R(Args...)>
55 {
56 private:
57 // Adjust as desired � must fit your expected lambdas
58 static constexpr std::size_t BufferSize = detail::max_sizeof_mfp();
59 static constexpr std::size_t BufferAlign = alignof(std::max_align_t);
60
61 using InvokeFn = R(*)(void*, Args&&...);
62 using CopyFn = void(*)(void*, const void*);
63 using MoveFn = void(*)(void*, void*);
64 using DestroyFn= void(*)(void*);
65
66 typename std::aligned_storage<BufferSize, BufferAlign>::type buffer;
67 InvokeFn invoke = nullptr;
68 CopyFn copy = nullptr;
69 MoveFn move = nullptr;
70 DestroyFn destroy = nullptr;
71
72 public:
73 any_lambda() = default;
74
75 any_lambda(std::nullptr_t) noexcept {}
76
77 any_lambda(const any_lambda& other)
78 {
79 if (other.invoke)
80 {
81 invoke = other.invoke;
82 copy = other.copy;
83 move = other.move;
84 destroy = other.destroy;
85 copy(&buffer, &other.buffer);
86 }
87 }
88
89 any_lambda(any_lambda&& other) noexcept
90 {
91 if (other.invoke)
92 {
93 invoke = other.invoke;
94 copy = other.copy;
95 move = other.move;
96 destroy = other.destroy;
97 move(&buffer, &other.buffer);
98 other.reset();
99 }
100 }
101
102 template<class F>
103 any_lambda(F f)
104 {
105 static_assert(!std::is_same<any_lambda, typename std::decay<F>::type>::value,
106 "cannot construct from self");
107 static_assert(sizeof(F) <= BufferSize, "lambda too large for buffer");
108 static_assert(alignof(F) <= BufferAlign, "lambda alignment too strict");
109
110 new (&buffer) F(std::move(f));
111
112 invoke = [](void* p, Args&&... args) -> R {
113 return (*static_cast<F*>(p))(std::forward<Args>(args)...);
114 };
115 copy = [](void* dst, const void* src) {
116 new (dst) F(*static_cast<const F*>(src));
117 };
118 move = [](void* dst, void* src) {
119 new (dst) F(std::move(*static_cast<F*>(src)));
120 static_cast<F*>(src)->~F();
121 };
122 destroy = [](void* p) { static_cast<F*>(p)->~F(); };
123 }
124
125 any_lambda& operator=(const any_lambda& other)
126 {
127 if (this != &other)
128 {
129 reset();
130 if (other.invoke)
131 {
132 invoke = other.invoke;
133 copy = other.copy;
134 move = other.move;
135 destroy = other.destroy;
136 copy(&buffer, &other.buffer);
137 }
138 }
139 return *this;
140 }
141
142 any_lambda& operator=(any_lambda&& other) noexcept
143 {
144 if (this != &other)
145 {
146 reset();
147 if (other.invoke)
148 {
149 invoke = other.invoke;
150 copy = other.copy;
151 move = other.move;
152 destroy = other.destroy;
153 move(&buffer, &other.buffer);
154 other.reset();
155 }
156 }
157 return *this;
158 }
159
160 ~any_lambda() { reset(); }
161
162 void reset()
163 {
164 if (destroy)
165 destroy(&buffer);
166 invoke = nullptr;//copy = move = destroy = nullptr;
167 }
168
169 explicit operator bool() const noexcept { return invoke != nullptr; }
170
171 R operator()(Args... args) const
172 {
173 if (!invoke)
174 throw std::bad_function_call();
175 return invoke(const_cast<void*>(static_cast<const void*>(&buffer)),
176 std::forward<Args>(args)...);
177 }
178 };
179 } // beast2
180 } // boost
181
182 #endif
183