Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:47

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 Catch::Detail::unique_ptr<callable> clone() const = 0;
0039                     virtual ~callable(); // = default;
0040 
0041                     callable() = default;
0042                     callable(callable const&) = default;
0043                     callable& operator=(callable const&) = default;
0044                 };
0045                 template <typename Fun>
0046                 struct model : public callable {
0047                     model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
0048                     model(Fun const& fun_) : fun(fun_) {}
0049 
0050                     Catch::Detail::unique_ptr<callable> clone() const override {
0051                         return Catch::Detail::make_unique<model<Fun>>( *this );
0052                     }
0053 
0054                     void call(Chronometer meter) const override {
0055                         call(meter, is_callable<Fun(Chronometer)>());
0056                     }
0057                     void call(Chronometer meter, std::true_type) const {
0058                         fun(meter);
0059                     }
0060                     void call(Chronometer meter, std::false_type) const {
0061                         meter.measure(fun);
0062                     }
0063 
0064                     Fun fun;
0065                 };
0066 
0067                 struct do_nothing { void operator()() const {} };
0068 
0069                 template <typename T>
0070                 BenchmarkFunction(model<T>* c) : f(c) {}
0071 
0072             public:
0073                 BenchmarkFunction()
0074                     : f(new model<do_nothing>{ {} }) {}
0075 
0076                 template <typename Fun,
0077                     std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
0078                     BenchmarkFunction(Fun&& fun)
0079                     : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
0080 
0081                 BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
0082                     f( CATCH_MOVE( that.f ) ) {}
0083 
0084                 BenchmarkFunction(BenchmarkFunction const& that)
0085                     : f(that.f->clone()) {}
0086 
0087                 BenchmarkFunction&
0088                 operator=( BenchmarkFunction&& that ) noexcept {
0089                     f = CATCH_MOVE( that.f );
0090                     return *this;
0091                 }
0092 
0093                 BenchmarkFunction& operator=(BenchmarkFunction const& that) {
0094                     f = that.f->clone();
0095                     return *this;
0096                 }
0097 
0098                 void operator()(Chronometer meter) const { f->call(meter); }
0099 
0100             private:
0101                 Catch::Detail::unique_ptr<callable> f;
0102             };
0103         } // namespace Detail
0104     } // namespace Benchmark
0105 } // namespace Catch
0106 
0107 #endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED