| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |     /* *  Created by Joachim on 16/04/2019. *  Adapted from donated nonius code. * *  Distributed under the Boost Software License, Version 1.0. (See accompanying *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ // Dumb std::function implementation for consistent call overhead#ifndef TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED#define TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED#include "../catch_chronometer.hpp"#include "catch_complete_invoke.hpp"#include "../../catch_meta.hpp"#include <cassert>#include <type_traits>#include <utility>#include <memory>namespace Catch {    namespace Benchmark {        namespace Detail {            template <typename T>            using Decay = typename std::decay<T>::type;            template <typename T, typename U>            struct is_related                : std::is_same<Decay<T>, Decay<U>> {};            /// We need to reinvent std::function because every piece of code that might add overhead            /// in a measurement context needs to have consistent performance characteristics so that we            /// can account for it in the measurement.            /// Implementations of std::function with optimizations that aren't always applicable, like            /// small buffer optimizations, are not uncommon.            /// This is effectively an implementation of std::function without any such optimizations;            /// it may be slow, but it is consistently slow.            struct BenchmarkFunction {            private:                struct callable {                    virtual void call(Chronometer meter) const = 0;                    virtual callable* clone() const = 0;                    virtual ~callable() = default;                };                template <typename Fun>                struct model : public callable {                    model(Fun&& fun) : fun(std::move(fun)) {}                    model(Fun const& fun) : fun(fun) {}                    model<Fun>* clone() const override { return new model<Fun>(*this); }                    void call(Chronometer meter) const override {                        call(meter, is_callable<Fun(Chronometer)>());                    }                    void call(Chronometer meter, std::true_type) const {                        fun(meter);                    }                    void call(Chronometer meter, std::false_type) const {                        meter.measure(fun);                    }                    Fun fun;                };                struct do_nothing { void operator()() const {} };                template <typename T>                BenchmarkFunction(model<T>* c) : f(c) {}            public:                BenchmarkFunction()                    : f(new model<do_nothing>{ {} }) {}                template <typename Fun,                    typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>                    BenchmarkFunction(Fun&& fun)                    : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}                BenchmarkFunction(BenchmarkFunction&& that)                    : f(std::move(that.f)) {}                BenchmarkFunction(BenchmarkFunction const& that)                    : f(that.f->clone()) {}                BenchmarkFunction& operator=(BenchmarkFunction&& that) {                    f = std::move(that.f);                    return *this;                }                BenchmarkFunction& operator=(BenchmarkFunction const& that) {                    f.reset(that.f->clone());                    return *this;                }                void operator()(Chronometer meter) const { f->call(meter); }            private:                std::unique_ptr<callable> f;            };        } // namespace Detail    } // namespace Benchmark} // namespace Catch#endif // TWOBLUECUBES_CATCH_DETAIL_BENCHMARK_FUNCTION_HPP_INCLUDED
 |