LCOV - code coverage report
Current view: top level - boost/beast2/server/any_lambda.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 32 0
Test Date: 2025-11-13 15:50:43 Functions: 0.0 % 9 0

            Line data    Source code
       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            0 :     any_lambda(const any_lambda& other)
      78            0 :     {
      79            0 :         if (other.invoke)
      80              :         {
      81            0 :             invoke = other.invoke;
      82            0 :             copy = other.copy;
      83            0 :             move = other.move;
      84            0 :             destroy = other.destroy;
      85            0 :             copy(&buffer, &other.buffer);
      86              :         }
      87            0 :     }
      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            0 :     any_lambda(F f)
     104            0 :     {
     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            0 :         new (&buffer) F(std::move(f));
     111              : 
     112            0 :         invoke = [](void* p, Args&&... args) -> R {
     113            0 :             return (*static_cast<F*>(p))(std::forward<Args>(args)...);
     114              :         };
     115            0 :         copy = [](void* dst, const void* src) {
     116            0 :             new (dst) F(*static_cast<const F*>(src));
     117              :         };
     118            0 :         move = [](void* dst, void* src) {
     119            0 :             new (dst) F(std::move(*static_cast<F*>(src)));
     120            0 :             static_cast<F*>(src)->~F();
     121              :         };
     122            0 :         destroy = [](void* p) { static_cast<F*>(p)->~F(); };
     123            0 :     }
     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            0 :     ~any_lambda() { reset(); }
     161              : 
     162            0 :     void reset()
     163              :     {
     164            0 :         if (destroy)
     165            0 :             destroy(&buffer);
     166            0 :         invoke = nullptr;//copy = move = destroy = nullptr;
     167            0 :     }
     168              : 
     169              :     explicit operator bool() const noexcept { return invoke != nullptr; }
     170              : 
     171            0 :     R operator()(Args... args) const
     172              :     {
     173            0 :         if (!invoke)
     174            0 :             throw std::bad_function_call();
     175            0 :         return invoke(const_cast<void*>(static_cast<const void*>(&buffer)),
     176            0 :                       std::forward<Args>(args)...);
     177              :     }
     178              : };
     179              : } // beast2
     180              : } // boost
     181              : 
     182              : #endif
        

Generated by: LCOV version 2.1