#include #include #include #include /** * @brief Wrapper for custom invoke operator available function types. * @note Source from: "Энтони Уильямс, Параллельное программирование на С++ в действии. Практика разработки многопоточных * программ. Пер. с англ. Слинкин А. А. - M.: ДМК Пресс, 2012 - 672c.: ил." (page 387) */ class FunctionWrapper { struct ImplBase { virtual void call() = 0; virtual ~ImplBase() = default; }; std::unique_ptr impl; template struct ImplType: ImplBase { F f; explicit ImplType(F&& f): f(std::forward(f)) {} void call() final { f(); } }; public: template::value> > explicit FunctionWrapper(F&& f): impl(new ImplType(std::forward(f))) {} void operator()() { impl->call(); } FunctionWrapper() = default; FunctionWrapper(FunctionWrapper&& other) noexcept : impl(std::move(other.impl)) {} FunctionWrapper& operator=(FunctionWrapper&& other) noexcept { impl = std::move(other.impl); return *this; } FunctionWrapper(const FunctionWrapper&) = delete; FunctionWrapper& operator=(const FunctionWrapper&) = delete; }; template float check_performance(Func test_function) { auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 5 * 1000 * 1000; ++i) { test_function(); } auto end = std::chrono::high_resolution_clock::now(); return std::chrono::duration_cast(end - start).count() / 1000.f; } int main() { std::queue queue; queue.push(std::move(FunctionWrapper())); FunctionWrapper functionWrapper = std::move(queue.front()); queue.pop(); auto test_lambda = [](){ int i = 0; while(i < 100) i++; }; float direct_call_performance = check_performance([&test_lambda](){ std::unique_ptr > test_function_p(new std::function(test_lambda)); test_function_p->operator()(); }); std::cout << "Direct call by pointer: " << direct_call_performance << " ms" << std::endl; float lambda_wrapper_performance = check_performance([&test_lambda](){ auto copy_lambda = test_lambda; FunctionWrapper wrapper(std::move(copy_lambda)); wrapper(); }); std::cout << "Lambda with function wrapper: " << lambda_wrapper_performance << " ms" << std::endl; float std_function_wrapper_performance = check_performance([&test_lambda](){ std::function test_function(test_lambda); FunctionWrapper wrapper(std::move(test_function)); wrapper(); }); std::cout << "std function with function wrapper: " << std_function_wrapper_performance << " ms" << std::endl; float packaged_task_wrapper_performance = check_performance([&test_lambda](){ std::packaged_task test_packaged_task(test_lambda); FunctionWrapper wrapper(test_packaged_task); wrapper(); }); std::cout << "Packaged task with function wrapper: " << packaged_task_wrapper_performance << " ms" << std::endl; return 0; }