164 lines
3.9 KiB
C
164 lines
3.9 KiB
C
![]() |
#ifndef BASE_UTIL_CALLBACK_H_
|
|||
|
#define BASE_UTIL_CALLBACK_H_
|
|||
|
#pragma once
|
|||
|
|
|||
|
#include <memory>
|
|||
|
#include <functional>
|
|||
|
#include "base/base_export.h"
|
|||
|
|
|||
|
typedef std::function<void(void)> StdClosure;
|
|||
|
|
|||
|
namespace nbase
|
|||
|
{
|
|||
|
|
|||
|
class WeakFlag
|
|||
|
{
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
template<typename T>
|
|||
|
class WeakCallback
|
|||
|
{
|
|||
|
public:
|
|||
|
WeakCallback(const std::weak_ptr<WeakFlag>& weak_flag, const T& t) :
|
|||
|
weak_flag_(weak_flag),
|
|||
|
t_(t)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
WeakCallback(const std::weak_ptr<WeakFlag>& weak_flag, T&& t) :
|
|||
|
weak_flag_(weak_flag),
|
|||
|
t_(std::move(t))
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
template<class WeakType>
|
|||
|
WeakCallback(const WeakType& weak_callback) :
|
|||
|
weak_flag_(weak_callback.weak_flag_),
|
|||
|
t_(weak_callback.t_)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
template<class... Args>
|
|||
|
auto operator ()(Args && ... args) const
|
|||
|
#if _MSC_VER > 1900
|
|||
|
#else
|
|||
|
->decltype(t_(std::forward<Args>(args)...))
|
|||
|
#endif
|
|||
|
{
|
|||
|
if (!weak_flag_.expired()) {
|
|||
|
return t_(std::forward<Args>(args)...);
|
|||
|
}
|
|||
|
return decltype(t_(std::forward<Args>(args)...))();
|
|||
|
}
|
|||
|
|
|||
|
bool Expired() const
|
|||
|
{
|
|||
|
return weak_flag_.expired();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
std::weak_ptr<WeakFlag> weak_flag_;
|
|||
|
mutable T t_;
|
|||
|
};
|
|||
|
|
|||
|
class BASE_EXPORT SupportWeakCallback
|
|||
|
{
|
|||
|
public:
|
|||
|
typedef std::weak_ptr<WeakFlag> _TyWeakFlag;
|
|||
|
public:
|
|||
|
virtual ~SupportWeakCallback(){};
|
|||
|
|
|||
|
template<typename CallbackType>
|
|||
|
auto ToWeakCallback(const CallbackType& closure)
|
|||
|
->WeakCallback<CallbackType>
|
|||
|
{
|
|||
|
return WeakCallback<CallbackType>(GetWeakFlag(), closure);
|
|||
|
}
|
|||
|
|
|||
|
std::weak_ptr<WeakFlag> GetWeakFlag()
|
|||
|
{
|
|||
|
if (m_weakFlag.use_count() == 0) {
|
|||
|
m_weakFlag.reset((WeakFlag*)NULL);
|
|||
|
}
|
|||
|
return m_weakFlag;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
template<typename ReturnValue, typename... Param, typename WeakFlag>
|
|||
|
static std::function<ReturnValue(Param...)> ConvertToWeakCallback(
|
|||
|
const std::function<ReturnValue(Param...)>& callback, std::weak_ptr<WeakFlag> expiredFlag)
|
|||
|
{
|
|||
|
auto weakCallback = [expiredFlag, callback](Param... p) {
|
|||
|
if (!expiredFlag.expired()) {
|
|||
|
return callback(p...);
|
|||
|
}
|
|||
|
return ReturnValue();
|
|||
|
};
|
|||
|
|
|||
|
return weakCallback;
|
|||
|
}
|
|||
|
|
|||
|
protected:
|
|||
|
std::shared_ptr<WeakFlag> m_weakFlag;
|
|||
|
};
|
|||
|
|
|||
|
//WeakCallbackFlagһ<67><D2BB><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>Ҫ<EFBFBD>̳У<CCB3><D0A3><EFBFBD>ʹ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD>Cancel()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>SupportWeakCallback
|
|||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>̳У<CCB3><D0A3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><D6A7>weak<61><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>callbackʱ<6B><CAB1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD>Cancel<65><6C>
|
|||
|
//<2F><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>callback<63><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD><DCB2><EFBFBD><EFBFBD>û<EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD>ġ<EFBFBD><C4A1><EFBFBD>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Cancel<65><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>WeakCallbackFlag<61><67><EFBFBD>͵ij<CDB5>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
//ÿ<><C3BF><EFBFBD><EFBFBD>Ӧһ<D3A6><D2BB>callback<63><6B>һһ<D2BB><D2BB>Ӧ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ÿ<EFBFBD><C3BF>֧<EFBFBD><D6A7>weak<61><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>callback<63><6B>
|
|||
|
class BASE_EXPORT WeakCallbackFlag final : public SupportWeakCallback
|
|||
|
{
|
|||
|
public:
|
|||
|
void Cancel()
|
|||
|
{
|
|||
|
m_weakFlag.reset();
|
|||
|
}
|
|||
|
|
|||
|
bool HasUsed()
|
|||
|
{
|
|||
|
return m_weakFlag.use_count() != 0;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
// global function
|
|||
|
template<class F, class... Args, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
|
|||
|
auto Bind(F && f, Args && ... args)
|
|||
|
->decltype(std::bind(f, args...))
|
|||
|
{
|
|||
|
return std::bind(f, args...);
|
|||
|
}
|
|||
|
|
|||
|
// const class member function
|
|||
|
template<class R, class C, class... DArgs, class P, class... Args>
|
|||
|
auto Bind(R(C::*f)(DArgs...) const, P && p, Args && ... args)
|
|||
|
->WeakCallback<decltype(std::bind(f, p, args...))>
|
|||
|
{
|
|||
|
std::weak_ptr<WeakFlag> weak_flag = ((SupportWeakCallback*)p)->GetWeakFlag();
|
|||
|
auto bind_obj = std::bind(f, p, args...);
|
|||
|
static_assert(std::is_base_of<nbase::SupportWeakCallback, C>::value, "nbase::SupportWeakCallback should be base of C");
|
|||
|
WeakCallback<decltype(bind_obj)> weak_callback(weak_flag, std::move(bind_obj));
|
|||
|
return weak_callback;
|
|||
|
}
|
|||
|
|
|||
|
// non-const class member function
|
|||
|
template<class R, class C, class... DArgs, class P, class... Args>
|
|||
|
auto Bind(R(C::*f)(DArgs...), P && p, Args && ... args)
|
|||
|
->WeakCallback<decltype(std::bind(f, p, args...))>
|
|||
|
{
|
|||
|
std::weak_ptr<WeakFlag> weak_flag = ((SupportWeakCallback*)p)->GetWeakFlag();
|
|||
|
auto bind_obj = std::bind(f, p, args...);
|
|||
|
static_assert(std::is_base_of<nbase::SupportWeakCallback, C>::value, "nbase::SupportWeakCallback should be base of C");
|
|||
|
WeakCallback<decltype(bind_obj)> weak_callback(weak_flag, std::move(bind_obj));
|
|||
|
return weak_callback;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif // BASE_UTIL_CALLBACK_H_
|