kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

commit e99023628731f61360916c3ecb2c1020c0a2fc61
parent 614f81271ede9d60093e36f868321b0e5254ac40
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Fri, 29 Nov 2019 11:24:15 +0000

New implementation for cometa::function

Diffstat:
Minclude/kfr/cometa/function.hpp | 131++++++++++++++++++++++++++++++++++---------------------------------------------
Mtests/asm_test.cpp | 3+++
2 files changed, 60 insertions(+), 74 deletions(-)

diff --git a/include/kfr/cometa/function.hpp b/include/kfr/cometa/function.hpp @@ -11,30 +11,6 @@ namespace cometa namespace details { -template <typename Result, typename... Args> -struct virtual_function -{ - virtual Result operator()(Args... args) = 0; - virtual virtual_function* make_copy() const = 0; - virtual ~virtual_function() = default; -}; - -template <typename Fn, typename Result, typename... Args> -struct virtual_function_impl : virtual_function<Result, Args...> -{ -public: - CMT_MEM_INTRINSIC virtual_function_impl(const Fn& fn) : fn(fn) {} - CMT_MEM_INTRINSIC Result operator()(Args... args) final { return fn(args...); } - CMT_MEM_INTRINSIC virtual_function<Result, Args...>* make_copy() const final - { - return new virtual_function_impl{ fn }; - } - CMT_MEM_INTRINSIC ~virtual_function_impl() {} - -private: - Fn fn; -}; - template <typename Fn> struct func_filter { @@ -58,9 +34,6 @@ constexpr CMT_INTRINSIC void return_val<void>() CMT_NOEXCEPT } } // namespace details -template <typename> -struct function; - /** * @brief std::function-like lightweight function wrapper * @code @@ -68,66 +41,76 @@ struct function; * CHECK( f( 3.4f ) == 3 ) * @endcode */ -template <typename Result, typename... Args> -struct function<Result(Args...)> +template <typename F> +struct function; + +namespace details +{ +template <typename R, typename... Args> +struct function_abstract { - using this_t = function<Result(Args...)>; + virtual ~function_abstract() {} + virtual R operator()(Args... args) = 0; +}; +template <typename Fn, typename R, typename... Args> +struct function_impl : public function_abstract<R, Args...> +{ + inline static void* operator new(size_t size) noexcept { return std::aligned_alloc(size, alignof(Fn)); } + inline static void operator delete(void* ptr) noexcept { return std::free(ptr); } + inline static void* operator new(size_t size, std::align_val_t al) noexcept + { + return std::aligned_alloc(size, static_cast<size_t>(al)); + } + inline static void operator delete(void* ptr, std::align_val_t al) noexcept { return std::free(ptr); } - function(function&& other) : fn(other.fn) { other.fn = nullptr; } - function& operator=(function&& other) + template <typename Fn_> + function_impl(Fn_ fn) : fn(std::forward<Fn_>(fn)) { - fn = other.fn; - other.fn = nullptr; - return *this; } + ~function_impl() override {} + R operator()(Args... args) override { return fn(std::forward<Args>(args)...); } + Fn fn; +}; +} // namespace details + +template <typename R, typename... Args> +struct function<R(Args...)> +{ + function() noexcept = default; + + function(nullptr_t) noexcept {} - CMT_MEM_INTRINSIC function() : fn(nullptr) {} - CMT_MEM_INTRINSIC function(std::nullptr_t) : fn(nullptr) {} - template <typename Func> - CMT_MEM_INTRINSIC function(const Func& x) - : fn(new details::virtual_function_impl<typename details::func_filter<Func>::type, Result, Args...>( - x)) + template <typename Fn, typename = std::enable_if_t<std::is_invocable_r_v<R, Fn, Args...> && + !std::is_same_v<std::decay_t<Fn>, function>>> + function(Fn fn) : impl(new internal::function_impl<std::decay_t<Fn>, R, Args...>(std::move(fn))) { } - function(const this_t& other) : fn(other.fn ? other.fn->make_copy() : nullptr) {} - CMT_MEM_INTRINSIC function& operator=(const this_t& other) + + function(const function&) = default; + + function(function&&) noexcept = default; + + function& operator=(const function&) = default; + + function& operator=(function&&) noexcept = default; + + R operator()(Args... args) const { - if ((&other != this) && (other.fn)) + if (impl) { - auto* temp = other.fn->make_copy(); - delete fn; - fn = temp; + return impl->operator()(std::forward<Args>(args)...); } - return *this; - } - CMT_MEM_INTRINSIC function& operator=(std::nullptr_t) - { - delete fn; - fn = nullptr; - return *this; - } - template <typename Fn> - CMT_MEM_INTRINSIC function& operator=(const Fn& x) - { - using FnImpl = - details::virtual_function_impl<typename details::func_filter<Fn>::type, Result, Args...>; - FnImpl* temp = new FnImpl(x); - delete fn; - fn = temp; - return *this; - } - CMT_MEM_INTRINSIC Result operator()(Args... args) const { return (*fn)(std::forward<Args>(args)...); } - template <typename TResult> - CMT_MEM_INTRINSIC Result call(TResult&& default_result, Args... args) const - { - return fn ? (*fn)(std::forward<Args>(args)...) : std::forward<TResult>(default_result); + throw std::bad_function_call(); } - CMT_MEM_INTRINSIC explicit operator bool() const CMT_NOEXCEPT { return !!fn; } - CMT_MEM_INTRINSIC ~function() { delete fn; } + [[nodiscard]] explicit operator bool() const { return !!impl; } + + [[nodiscard]] bool empty() const { return !impl; } + + std::shared_ptr<details::function_abstract<R, Args...>> impl; -private: - details::virtual_function<Result, Args...>* fn; + bool operator==(const function& fn) const { return impl == fn.impl; } + bool operator!=(const function& fn) const { return !operator==(fn); } }; template <typename Ret, typename... Args, typename T, typename Fn, typename DefFn = fn_noop> diff --git a/tests/asm_test.cpp b/tests/asm_test.cpp @@ -6,6 +6,9 @@ #define KFR_EXTENDED_TESTS +#include <type_traits> +#include <utility> + #include <kfr/base.hpp> #include <kfr/dsp.hpp> #ifdef HAVE_DFT