123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #ifndef BASE_CALLBACK_LIST_H_
- #define BASE_CALLBACK_LIST_H_
- #include <algorithm>
- #include <list>
- #include <memory>
- #include <utility>
- #include "base/auto_reset.h"
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/check.h"
- #include "base/compiler_specific.h"
- #include "base/memory/weak_ptr.h"
- #include "base/stl_util.h"
- namespace base {
- template <typename Signature>
- class OnceCallbackList;
- template <typename Signature>
- class RepeatingCallbackList;
- namespace internal {
- template <typename CallbackList>
- struct CallbackListTraits;
- template <typename Signature>
- struct CallbackListTraits<OnceCallbackList<Signature>> {
- using CallbackType = OnceCallback<Signature>;
- using Callbacks = std::list<CallbackType>;
- };
- template <typename Signature>
- struct CallbackListTraits<RepeatingCallbackList<Signature>> {
- using CallbackType = RepeatingCallback<Signature>;
- using Callbacks = std::list<CallbackType>;
- };
- template <typename CallbackListImpl>
- class CallbackListBase {
- public:
- using CallbackType =
- typename CallbackListTraits<CallbackListImpl>::CallbackType;
- static_assert(IsBaseCallback<CallbackType>::value, "");
-
-
-
- class Subscription {
- public:
- explicit Subscription(base::OnceClosure destruction_closure)
- : destruction_closure_(std::move(destruction_closure)) {}
- Subscription(Subscription&&) = default;
- Subscription& operator=(Subscription&&) = default;
- ~Subscription() { std::move(destruction_closure_).Run(); }
- private:
-
-
-
-
- base::OnceClosure destruction_closure_;
- };
- CallbackListBase() = default;
- CallbackListBase(const CallbackListBase&) = delete;
- CallbackListBase& operator=(const CallbackListBase&) = delete;
- ~CallbackListBase() {
-
- CHECK(!iterating_);
- }
-
-
- std::unique_ptr<Subscription> Add(CallbackType cb) WARN_UNUSED_RESULT {
- DCHECK(!cb.is_null());
- return std::make_unique<Subscription>(base::BindOnce(
- &CallbackListBase::CancelCallback, weak_ptr_factory_.GetWeakPtr(),
- callbacks_.insert(callbacks_.end(), std::move(cb))));
- }
-
-
-
-
-
-
- void AddUnsafe(CallbackType cb) {
- DCHECK(!cb.is_null());
- callbacks_.push_back(std::move(cb));
- }
-
-
- void set_removal_callback(const RepeatingClosure& removal_callback) {
- removal_callback_ = removal_callback;
- }
-
-
- bool empty() const {
- return std::all_of(callbacks_.cbegin(), callbacks_.cend(),
- [](const auto& callback) { return callback.is_null(); });
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- template <typename... RunArgs>
- void Notify(RunArgs&&... args) {
- if (empty())
- return;
- {
- AutoReset<bool> iterating(&iterating_, true);
-
-
-
- const auto next_valid = [this](const auto it) {
- return std::find_if_not(it, callbacks_.end(), [](const auto& callback) {
- return callback.is_null();
- });
- };
- for (auto it = next_valid(callbacks_.begin()); it != callbacks_.end();
- it = next_valid(it))
-
-
- static_cast<CallbackListImpl*>(this)->RunCallback(it++, args...);
- }
-
-
-
-
- if (iterating_)
- return;
-
-
- const size_t erased_callbacks =
- EraseIf(callbacks_, [](const auto& cb) { return cb.is_null(); });
-
-
-
-
-
-
- if (removal_callback_ &&
- (erased_callbacks || IsOnceCallback<CallbackType>::value))
- removal_callback_.Run();
- }
- protected:
- using Callbacks = typename CallbackListTraits<CallbackListImpl>::Callbacks;
-
- Callbacks callbacks_;
- private:
-
- void CancelCallback(const typename Callbacks::iterator& it) {
- if (static_cast<CallbackListImpl*>(this)->CancelNullCallback(it))
- return;
- if (iterating_) {
-
-
-
-
- it->Reset();
- } else {
- callbacks_.erase(it);
- if (removal_callback_)
- removal_callback_.Run();
- }
- }
-
-
- bool iterating_ = false;
-
- RepeatingClosure removal_callback_;
- WeakPtrFactory<CallbackListBase> weak_ptr_factory_{this};
- };
- }
- template <typename Signature>
- class OnceCallbackList
- : public internal::CallbackListBase<OnceCallbackList<Signature>> {
- private:
- friend internal::CallbackListBase<OnceCallbackList>;
- using Traits = internal::CallbackListTraits<OnceCallbackList>;
-
- template <typename... RunArgs>
- void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) {
-
-
- null_callbacks_.splice(null_callbacks_.end(), this->callbacks_, it);
-
-
- std::move(*it).Run(args...);
- }
-
-
- bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
- if (it->is_null()) {
- null_callbacks_.erase(it);
- return true;
- }
- return false;
- }
-
-
-
-
- typename Traits::Callbacks null_callbacks_;
- };
- template <typename Signature>
- class RepeatingCallbackList
- : public internal::CallbackListBase<RepeatingCallbackList<Signature>> {
- private:
- friend internal::CallbackListBase<RepeatingCallbackList>;
- using Traits = internal::CallbackListTraits<RepeatingCallbackList>;
-
- template <typename... RunArgs>
- void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) {
-
-
- it->Run(args...);
- }
-
-
- bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
-
-
-
- DCHECK(!it->is_null());
- return false;
- }
- };
- template <typename Signature>
- using CallbackList = RepeatingCallbackList<Signature>;
- using OnceClosureList = OnceCallbackList<void()>;
- using RepeatingClosureList = RepeatingCallbackList<void()>;
- using ClosureList = CallbackList<void()>;
- }
- #endif
|