Commit 9a414758 authored by Dominik Charousset's avatar Dominik Charousset

Add support for heap-allocated callbacks

parent 9e060c37
...@@ -19,38 +19,47 @@ ...@@ -19,38 +19,47 @@
#pragma once #pragma once
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/error.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/error.hpp"
// The class `callback` intentionally has no virtual destructor, because #include <memory>
// the lifetime of callback objects is never managed via base pointers.
CAF_PUSH_NON_VIRTUAL_DTOR_WARNING
namespace caf { namespace caf {
/// Describes a simple callback, usually implemented via lambda expression. /// Describes a simple callback, usually implemented via lambda expression.
/// Callbacks are used as "type-safe function objects" wherever an interface /// Callbacks are used as "type-safe function objects" wherever an interface
/// requires dynamic dispatching. The alternative would be to store the lambda /// requires dynamic dispatching. The alternative would be to store the lambda
/// in a `std::function`, which adds another layer of indirection and /// in a `std::function`, which adds another layer of indirection and always
/// requires a heap allocation. With the callback implementation of CAF, /// requires a heap allocation. With the callback implementation of CAF, the
/// the object remains on the stack and does not cause more overhead /// object may remains on the stack and do not cause more overhead than
/// than necessary. /// necessary.
template <class Signature> template <class Signature>
class callback; class callback;
template <class Result, class... Ts> template <class Result, class... Ts>
class callback<Result(Ts...)> { class callback<Result(Ts...)> {
public: public:
virtual ~callback() {
// nop
}
virtual Result operator()(Ts...) = 0; virtual Result operator()(Ts...) = 0;
}; };
/// Smart pointer type for heap-allocated callbacks with unique ownership.
template <class Signature>
using unique_callback_ptr = std::unique_ptr<callback<Signature>>;
/// Smart pointer type for heap-allocated callbacks with shared ownership.
template <class Signature>
using shared_callback_ptr = std::shared_ptr<callback<Signature>>;
/// Utility class for wrapping a function object of type `F`. /// Utility class for wrapping a function object of type `F`.
template <class F, class Signature> template <class F, class Signature>
class callback_impl; class callback_impl;
template <class F, class Result, class... Ts> template <class F, class Result, class... Ts>
class callback_impl<F, Result(Ts...)> : public callback<Result(Ts...)> { class callback_impl<F, Result(Ts...)> final : public callback<Result(Ts...)> {
public: public:
callback_impl(F&& f) : f_(std::move(f)) { callback_impl(F&& f) : f_(std::move(f)) {
// nop // nop
...@@ -68,7 +77,7 @@ private: ...@@ -68,7 +77,7 @@ private:
F f_; F f_;
}; };
/// Creates a ::callback from the function object `fun`. /// Wraps `fun` into a @ref callback function object.
/// @relates callback /// @relates callback
template <class F> template <class F>
auto make_callback(F fun) { auto make_callback(F fun) {
...@@ -76,6 +85,24 @@ auto make_callback(F fun) { ...@@ -76,6 +85,24 @@ auto make_callback(F fun) {
return callback_impl<F, signature>{std::move(fun)}; return callback_impl<F, signature>{std::move(fun)};
} }
} // namespace caf /// Creates a heap-allocated, type-erased @ref callback from the function object
/// `fun`.
/// @relates callback
template <class F>
auto make_type_erased_callback(F fun) {
using signature = typename detail::get_callable_trait<F>::fun_sig;
using result_t = unique_callback_ptr<signature>;
return result_t{new callback_impl<F, signature>{std::move(fun)}};
}
/// Creates a heap-allocated, type-erased @ref callback from the function object
/// `fun` with shared ownership.
/// @relates callback
template <class F>
auto make_shared_type_erased_callback(F fun) {
using signature = typename detail::get_callable_trait<F>::fun_sig;
auto res = std::make_shared<callback_impl<F, signature>>(std::move(fun));
return shared_callback_ptr<signature>{std::move(res)};
}
CAF_POP_WARNINGS } // namespace caf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment