Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-08 10:02:49

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 // Adapted from donated nonius code.
0009 
0010 #ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
0011 #define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
0012 
0013 #include <catch2/benchmark/catch_chronometer.hpp>
0014 #include <catch2/internal/catch_meta.hpp>
0015 #include <catch2/internal/catch_unique_ptr.hpp>
0016 #include <catch2/internal/catch_move_and_forward.hpp>
0017 
0018 #include <type_traits>
0019 
0020 namespace Catch {
0021     namespace Benchmark {
0022         namespace Detail {
0023             template <typename T, typename U>
0024             struct is_related
0025                 : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
0026 
0027             /// We need to reinvent std::function because every piece of code that might add overhead
0028             /// in a measurement context needs to have consistent performance characteristics so that we
0029             /// can account for it in the measurement.
0030             /// Implementations of std::function with optimizations that aren't always applicable, like
0031             /// small buffer optimizations, are not uncommon.
0032             /// This is effectively an implementation of std::function without any such optimizations;
0033             /// it may be slow, but it is consistently slow.
0034             struct BenchmarkFunction {
0035             private:
0036                 struct callable {
0037                     virtual void call(Chronometer meter) const = 0;
0038                     virtual ~callable(); // = default;
0039 
0040                     callable() = default;
0041                     callable(callable&&) = default;
0042                     callable& operator=(callable&&) = default;
0043                 };
0044                 template <typename Fun>
0045                 struct model : public callable {
0046                     model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
0047                     model(Fun const& fun_) : fun(fun_) {}
0048 
0049                     void call(Chronometer meter) const override {
0050                         call(meter, is_callable<Fun(Chronometer)>());
0051                     }
0052                     void call(Chronometer meter, std::true_type) const {
0053                         fun(meter);
0054                     }
0055                     void call(Chronometer meter, std::false_type) const {
0056                         meter.measure(fun);
0057                     }
0058 
0059                     Fun fun;
0060                 };
0061 
0062             public:
0063                 BenchmarkFunction();
0064 
0065                 template <typename Fun,
0066                     std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
0067                     BenchmarkFunction(Fun&& fun)
0068                     : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
0069 
0070                 BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
0071                     f( CATCH_MOVE( that.f ) ) {}
0072 
0073                 BenchmarkFunction&
0074                 operator=( BenchmarkFunction&& that ) noexcept {
0075                     f = CATCH_MOVE( that.f );
0076                     return *this;
0077                 }
0078 
0079                 void operator()(Chronometer meter) const { f->call(meter); }
0080 
0081             private:
0082                 Catch::Detail::unique_ptr<callable> f;
0083             };
0084         } // namespace Detail
0085     } // namespace Benchmark
0086 } // namespace Catch
0087 
0088 #endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED