diff --git a/fluent/Callback.h b/fluent/Callback.h new file mode 100644 index 0000000..d8f22de --- /dev/null +++ b/fluent/Callback.h @@ -0,0 +1,112 @@ + +/* + * Copyright (C) 2015 Naios + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _CALLBACK_H_ +#define _CALLBACK_H_ + +#include +#include +#include + +#include "functional_unwrap.hpp" + +template +using Callback = std::function; + +template +using SharedCallback = std::shared_ptr>; + +template +using WeakCallback = std::weak_ptr>; + +namespace detail +{ + template + struct do_unwrap_callback; + + template + struct do_unwrap_callback> + { + typedef Callback<_ATy...> CallbackType; + + typedef SharedCallback<_ATy...> SharedCallbackType; + + typedef WeakCallback<_ATy...> WeakCallbackType; + }; + + template + using unwrap_callback_t = do_unwrap_callback<::fu::function_type_of_t<_CTy>>; + + /* + template + struct WeakProxyFactory + { + static Callback CreateProxyFromWeak(WeakCallback const& weak_callback) + { + return [=](Args&&... args) + { + if (auto const callback = weak_callback.lock()) + (*callback)(args...); // FIXME: use std::forward + }; + } + + static Callback CreateProxyFromShared(SharedCallback const& shared_callback) + { + return CreateProxyFromWeak(WeakCallback(shared_callback)); + } + }; + */ + +} // detail + +template +using callback_of_t = typename detail::unwrap_callback_t<_CTy>::CallbackType; + +template +using shared_callback_of_t = typename detail::unwrap_callback_t<_CTy>::SharedCallbackType; + +template +using weak_callback_of_t = typename detail::unwrap_callback_t<_CTy>::WeakCallbackType; + +template +inline shared_callback_of_t<_CTy> + make_shared_callback(_CTy&& callback) +{ + return std::make_shared> + (std::forward>(callback)); +}; + +/* Disabled due to clang errors +template +inline auto make_weak_wrapped_callback(WeakCallback const& weak_callback) + -> Callback +{ + // Some workarounds for clang... + return detail::WeakProxyFactory::CreateProxyFromWeak(weak_callback); +} + +template +inline auto make_weak_wrapped_callback(SharedCallback const& shared_callback) + -> Callback +{ + // Some workarounds for clang... + return detail::WeakProxyFactory::CreateProxyFromShared(shared_callback); +} +*/ + +#endif /// _CALLBACK_H_ diff --git a/fluent/Continuable.h b/fluent/Continuable.h new file mode 100644 index 0000000..f3f98e1 --- /dev/null +++ b/fluent/Continuable.h @@ -0,0 +1,81 @@ + +/* + * Copyright (C) 2015 Naios + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _CONTINUABLE_H_ +#define _CONTINUABLE_H_ + +#include "Callback.h" + +template +struct Continuable +{ + typedef Callback&&> ForwardFunction; + + // Function which expects a callback that is inserted from the Continuable + // to chain everything together + ForwardFunction _callback_insert; + + Continuable<_ATy...>() { } + Continuable<_ATy...>(ForwardFunction&& callback_insert) + : _callback_insert(std::forward(callback_insert)) { } + + template + Continuable<_ATy...>& then(_CTy&&) + { + return *this; + } +}; + +namespace detail +{ + template + struct ContinuableFactory; + + template + struct ContinuableFactory<_FTy, _RTy, ::fu::identity&&>> + { + static auto CreateFrom(_FTy&& functional) + -> Continuable<_ATy...> + { + return Continuable<_ATy...>( + typename Continuable<_ATy...>::ForwardFunction(std::forward<_FTy>(functional))); + } + }; + + template + using continuable_factory_t = ContinuableFactory< + _FTy, ::fu::return_type_of_t<_FTy>, ::fu::argument_type_of_t<_FTy>>; + +} // detail + +/// Wraps a functional object which expects a r-value callback as argument into a continuable. +/// The callable is invoked when the continuable shall continue. +/// For example: +/// make_continuable([](Callback&& callback) +/// { +/// /* Continue here */ +/// callback(5); +/// }); +template +inline auto make_continuable(_FTy&& functional) + -> decltype(detail::continuable_factory_t<_FTy>::CreateFrom(std::declval<_FTy>())) +{ + return detail::continuable_factory_t<_FTy>::CreateFrom(std::forward<_FTy>(functional)); +} + +#endif /// _CONTINUABLE_H_ diff --git a/fluent/WeakCallbackContainer.h b/fluent/WeakCallbackContainer.h new file mode 100644 index 0000000..b68e997 --- /dev/null +++ b/fluent/WeakCallbackContainer.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008-2015 TrinityCore + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef _WEAK_CALLBACK_CONTAINER_H_ +#define _WEAK_CALLBACK_CONTAINER_H_ + +#include + +#include +#include + +#include "Callback.h" + +class WeakCallbackContainer +{ + std::shared_ptr self_reference; + + typedef size_t handle_t; + + size_t handle; + + std::unordered_map container; + + template + struct ProxyFactory; + + template + struct ProxyFactory<_CTy, ::fu::identity> + { + // Creates a weak proxy callback which prevents invoking to an invalid context. + // Removes itself from the owner with the given handler. + static callback_of_t<_CTy> CreateProxy(std::weak_ptr const& weak_owner, + size_t const handle, weak_callback_of_t<_CTy> const& weak_callback) + { + return [=](Args&&... args) + { + // Try to get a pointer to the owner + if (auto const owner = weak_owner.lock()) + // And to the wrapped functional itself + if (auto const callback = weak_callback.lock()) + { + // Invoke the original callback + (*callback)(args...); // FIXME: use std::forward + + // Unregister the callback + owner->InvalidateCallback(handle); + } + }; + } + }; + +public: + WeakCallbackContainer() + : self_reference(this, [](decltype(this)) { }), handle(0L) { } + + ~WeakCallbackContainer() = default; + + WeakCallbackContainer(WeakCallbackContainer const&) = delete; + WeakCallbackContainer(WeakCallbackContainer&&) = delete; + + WeakCallbackContainer& operator= (WeakCallbackContainer const&) = delete; + WeakCallbackContainer& operator= (WeakCallbackContainer&&) = delete; + + WeakCallbackContainer& Clear() + { + container.clear(); + return *this; + } + + /// Weak wraps the given callable. + template + auto Wrap(_CTy&& callback) + -> callback_of_t<_CTy> + { + // Create the shared callback + shared_callback_of_t<_CTy> shared_callback = make_shared_callback(std::forward<_CTy>(callback)); + + // Create a weak proxy callback which removes the callback on execute + auto const this_handle = handle++; + callback_of_t<_CTy> proxy = + ProxyFactory<_CTy, ::fu::argument_type_of_t<_CTy>>:: + CreateProxy(self_reference, this_handle, shared_callback); + + container.insert(std::make_pair(this_handle, boost::any(std::move(shared_callback)))); + return std::move(proxy); + } + + /// Calls ::Wrap on the given callable, + template + inline auto operator()(_CTy&& callback) + -> decltype(Wrap(std::declval<_CTy>())) + { + return Wrap(std::forward<_CTy>(callback)); + } + + boost::optional GetLastCallbackHandle() const + { + if (handle == 0L) + return boost::none; + else + return boost::make_optional(handle); + } + + WeakCallbackContainer& InvalidateCallback(handle_t const handle) + { + container.erase(handle); + return *this; + } +}; + +#endif /// _WEAK_CALLBACK_CONTAINER_H_ diff --git a/fluent/fluent++.cpp b/fluent/fluent++.cpp new file mode 100644 index 0000000..aa130e1 --- /dev/null +++ b/fluent/fluent++.cpp @@ -0,0 +1,4 @@ + +#include "fluent++.hpp" + +void do_export() { } diff --git a/fluent/fluent++.hpp b/fluent/fluent++.hpp new file mode 100644 index 0000000..b28efc8 --- /dev/null +++ b/fluent/fluent++.hpp @@ -0,0 +1,90 @@ + +#ifndef _FLUENT_HPP_ +#define _FLUENT_HPP_ + +#include +#include +#include + +#include "functional_unwrap.hpp" + +/* +class fluent_step +{ + bool released; + + void release() + { + int i = 0; + + std::cout << "-> release" << std::endl; + } + +public: + fluent_step() : released(false) + { + std::cout << "+ construct" << std::endl; + } + + ~fluent_step() + { + std::cout << "- destruct" << std::endl; + + if (!released) + release(); + } + + fluent_step(fluent_step const&) = delete; + fluent_step(fluent_step&& right) : released(false) + { + std::cout << "<-> move" << std::endl; + + right.released = true; + } + + fluent_step& operator= (fluent_step const&) = delete; + fluent_step& operator= (fluent_step&& right) + { + released = false; + right.released = true; + return *this; + } + + template + fluent_step then(Callback&& callback) + { + return std::move(*this); + } +}; + +template +fluent_step make_waterfall() +{ + return fluent_step(); +} + + +struct ProtoContinueable +{ + template + ProtoContinueable then(Callback&& callback) + { + return ProtoContinueable(); + } + + template + ProtoContinueable weak(Container& container) + { + return ProtoContinueable(); + } + + ProtoContinueable strong() + { + return ProtoContinueable(); + } +}; +*/ + +void do_export(); + +#endif /// _FLUENT_HPP_ diff --git a/fluent/functional_unwrap.hpp b/fluent/functional_unwrap.hpp new file mode 100644 index 0000000..481f587 --- /dev/null +++ b/fluent/functional_unwrap.hpp @@ -0,0 +1,146 @@ + +/* + * Copyright (C) 2015 Naios + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * The functional unwrap trait provides the possibility to extract + * various types out of c++ functional types, like std::function, functors and more. + */ + +#ifndef _FUNCTIONAL_UNWRAP_HPP_ +#define _FUNCTIONAL_UNWRAP_HPP_ + +#include + +namespace fu +{ + template + struct identity + { + }; + + namespace detail + { + template + struct unwrap_function_impl; + + template + struct unwrap_function_impl<_RTy(_ATy...)> + { + /// The return type of the function. + typedef _RTy return_type; + + /// The argument types of the function as pack in fu::identity. + typedef identity<_ATy...> argument_type; + + /// The function provided as std::function + typedef std::function<_RTy(_ATy...)> function_type; + + /// The function provided as function_ptr + typedef _RTy(*function_ptr)(_ATy...); + }; + + /// STL: std::function + template + struct unwrap_function_impl> + : unwrap_function_impl<_RTy(_ATy...)> { }; + + /// STL: std::tuple + template + struct unwrap_function_impl> + : unwrap_function_impl<_RTy(_ATy...)> { }; + + /// Function pointers + template + struct unwrap_function_impl<_RTy(*const)(_ATy...)> + : unwrap_function_impl<_RTy(_ATy...)> { }; + + /// Class Method pointers + template + struct unwrap_function_impl<_RTy(_CTy::*)(_ATy...) const> + : unwrap_function_impl<_RTy(_ATy...)> { }; + + /// Pack in fu::identity + template + struct unwrap_function_impl> + : unwrap_function_impl<_RTy(_ATy...)> { }; + + /// Unwrap through pointer of functor. + template + static auto select_best_unwrap_unary_arg(int) + -> unwrap_function_impl; + + /// Unwrap through plain type. + template + static auto select_best_unwrap_unary_arg(long) + -> unwrap_function_impl; + + template + struct select_best_unwrap; + + /// Enable only if 1 template argument is given. + template + struct select_best_unwrap<_FTy> + { + typedef decltype(select_best_unwrap_unary_arg<_FTy>(0)) type; + }; + + // Enable if more then 1 template argument is given. + // (Handles lazy typing) + template + struct select_best_unwrap<_RTy, _ATy...> + { + typedef unwrap_function_impl<_RTy(_ATy...)> type; + }; + + } // detail + + /// Trait to unwrap function parameters of various types: + /// Function style definition: Result(Parameters...) + /// STL `std::function` : std::function + /// STL `std::tuple` : std::tuple + /// C++ Function pointers: `Result(*)(Parameters...)` + /// C++ Class method pointers: `Result(Class::*)(Parameters...)` + /// Lazy typed signatures: `Result, Parameters...` + /// Also provides optimized unwrap of functors and functional objects. + template + using unwrap_function = + typename detail::select_best_unwrap::type; + + /// Trait which defines the return type of the function. + template + using return_type_of_t = + typename detail::select_best_unwrap::type::return_type; + + /// Trait which defines the argument types of the function packed in std::tuple. + template + using argument_type_of_t = + typename detail::select_best_unwrap::type::argument_type; + + /// Trait which defines the std::function type of the function. + template + using function_type_of_t = + typename detail::select_best_unwrap::type::function_type; + + /// Trait which defines the function pointer type of the function. + template + using function_ptr_of_t = + typename detail::select_best_unwrap::type::function_ptr; + +} // fu + +#endif // _FUNCTIONAL_UNWRAP_HPP_