#ifndef BASE_CANCELABLE_CALLBACK_H_
#define BASE_CANCELABLE_CALLBACK_H_
#include <utility>
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_internal.h"
#include "base/memory/weak_ptr.h"
namespace base {
namespace internal {
template <typename CallbackType>
class CancelableCallbackImpl {
public:
CancelableCallbackImpl() = default;
CancelableCallbackImpl(const CancelableCallbackImpl&) = delete;
CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete;
explicit CancelableCallbackImpl(CallbackType callback)
: callback_(std::move(callback)) {
DCHECK(callback_);
}
~CancelableCallbackImpl() = default;
void Cancel() {
weak_ptr_factory_.InvalidateWeakPtrs();
callback_.Reset();
}
bool IsCancelled() const {
return callback_.is_null();
}
void Reset(CallbackType callback) {
DCHECK(callback);
Cancel();
callback_ = std::move(callback);
}
CallbackType callback() const {
if (!callback_)
return CallbackType();
CallbackType forwarder;
MakeForwarder(&forwarder);
return forwarder;
}
private:
template <typename... Args>
void MakeForwarder(RepeatingCallback<void(Args...)>* out) const {
using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
ForwarderType forwarder = &CancelableCallbackImpl::ForwardRepeating;
*out = BindRepeating(forwarder, weak_ptr_factory_.GetWeakPtr());
}
template <typename... Args>
void MakeForwarder(OnceCallback<void(Args...)>* out) const {
using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
ForwarderType forwarder = &CancelableCallbackImpl::ForwardOnce;
*out = BindOnce(forwarder, weak_ptr_factory_.GetWeakPtr());
}
template <typename... Args>
void ForwardRepeating(Args... args) {
callback_.Run(std::forward<Args>(args)...);
}
template <typename... Args>
void ForwardOnce(Args... args) {
weak_ptr_factory_.InvalidateWeakPtrs();
std::move(callback_).Run(std::forward<Args>(args)...);
}
CallbackType callback_;
mutable base::WeakPtrFactory<CancelableCallbackImpl> weak_ptr_factory_{this};
};
}
template <typename Signature>
using CancelableOnceCallback =
internal::CancelableCallbackImpl<OnceCallback<Signature>>;
using CancelableOnceClosure = CancelableOnceCallback<void()>;
template <typename Signature>
using CancelableRepeatingCallback =
internal::CancelableCallbackImpl<RepeatingCallback<Signature>>;
using CancelableRepeatingClosure = CancelableRepeatingCallback<void()>;
}
#endif