#ifndef BASE_UTIL_CALLBACK_H_ #define BASE_UTIL_CALLBACK_H_ #pragma once #include #include #include "base/base_export.h" typedef std::function StdClosure; namespace nbase { class WeakFlag { }; template class WeakCallback { public: WeakCallback(const std::weak_ptr& weak_flag, const T& t) : weak_flag_(weak_flag), t_(t) { } WeakCallback(const std::weak_ptr& weak_flag, T&& t) : weak_flag_(weak_flag), t_(std::move(t)) { } template WeakCallback(const WeakType& weak_callback) : weak_flag_(weak_callback.weak_flag_), t_(weak_callback.t_) { } template auto operator ()(Args && ... args) const #if _MSC_VER > 1900 #else ->decltype(t_(std::forward(args)...)) #endif { if (!weak_flag_.expired()) { return t_(std::forward(args)...); } return decltype(t_(std::forward(args)...))(); } bool Expired() const { return weak_flag_.expired(); } std::weak_ptr weak_flag_; mutable T t_; }; class BASE_EXPORT SupportWeakCallback { public: typedef std::weak_ptr _TyWeakFlag; public: virtual ~SupportWeakCallback(){}; template auto ToWeakCallback(const CallbackType& closure) ->WeakCallback { return WeakCallback(GetWeakFlag(), closure); } std::weak_ptr GetWeakFlag() { if (m_weakFlag.use_count() == 0) { m_weakFlag.reset((WeakFlag*)NULL); } return m_weakFlag; } private: template static std::function ConvertToWeakCallback( const std::function& callback, std::weak_ptr expiredFlag) { auto weakCallback = [expiredFlag, callback](Param... p) { if (!expiredFlag.expired()) { return callback(p...); } return ReturnValue(); }; return weakCallback; } protected: std::shared_ptr m_weakFlag; }; //WeakCallbackFlag一般作为类成员变量使用,要继承,可使用不带Cancel()函数的SupportWeakCallback //这里禁止继承,主要担心误用。当使用这个类的功能,打包出多个支持weak语义的callback时,一旦错误的调用了Cancel, //将会取消所有callback,这种情况可能不是用户希望的。此时,应该使用多个不带Cancel函数的WeakCallbackFlag类型的成员变量, //每个对应一个callback,一一对应的控制每个支持weak语义的callback。 class BASE_EXPORT WeakCallbackFlag final : public SupportWeakCallback { public: void Cancel() { m_weakFlag.reset(); } bool HasUsed() { return m_weakFlag.use_count() != 0; } }; // global function template::value>::type> auto Bind(F && f, Args && ... args) ->decltype(std::bind(f, args...)) { return std::bind(f, args...); } // const class member function template auto Bind(R(C::*f)(DArgs...) const, P && p, Args && ... args) ->WeakCallback { std::weak_ptr weak_flag = ((SupportWeakCallback*)p)->GetWeakFlag(); auto bind_obj = std::bind(f, p, args...); static_assert(std::is_base_of::value, "nbase::SupportWeakCallback should be base of C"); WeakCallback weak_callback(weak_flag, std::move(bind_obj)); return weak_callback; } // non-const class member function template auto Bind(R(C::*f)(DArgs...), P && p, Args && ... args) ->WeakCallback { std::weak_ptr weak_flag = ((SupportWeakCallback*)p)->GetWeakFlag(); auto bind_obj = std::bind(f, p, args...); static_assert(std::is_base_of::value, "nbase::SupportWeakCallback should be base of C"); WeakCallback weak_callback(weak_flag, std::move(bind_obj)); return weak_callback; } } #endif // BASE_UTIL_CALLBACK_H_