#ifndef BASE_OBSERVER_LIST_INTERNAL_H_
#define BASE_OBSERVER_LIST_INTERNAL_H_
#include <string>
#include "base/base_export.h"
#include "base/check.h"
#include "base/containers/linked_list.h"
#include "base/dcheck_is_on.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list_types.h"
#if DCHECK_IS_ON()
#include "base/debug/stack_trace.h"
#endif
namespace base {
namespace internal {
class BASE_EXPORT UncheckedObserverAdapter {
public:
explicit UncheckedObserverAdapter(const void* observer)
: ptr_(const_cast<void*>(observer)) {}
UncheckedObserverAdapter(const UncheckedObserverAdapter&) = delete;
UncheckedObserverAdapter& operator=(const UncheckedObserverAdapter&) = delete;
UncheckedObserverAdapter(UncheckedObserverAdapter&& other) = default;
UncheckedObserverAdapter& operator=(UncheckedObserverAdapter&& other) =
default;
void MarkForRemoval() { ptr_ = nullptr; }
bool IsMarkedForRemoval() const { return !ptr_; }
bool IsEqual(const void* rhs) const { return ptr_ == rhs; }
template <class ObserverType>
static ObserverType* Get(const UncheckedObserverAdapter& adapter) {
static_assert(
!std::is_base_of<CheckedObserver, ObserverType>::value,
"CheckedObserver classes must not use ObserverList<T>::Unchecked.");
return static_cast<ObserverType*>(adapter.ptr_);
}
#if DCHECK_IS_ON()
std::string GetCreationStackString() const { return stack_.ToString(); }
#endif
private:
raw_ptr<void, DanglingUntriaged> ptr_;
#if DCHECK_IS_ON()
base::debug::StackTrace stack_;
#endif
};
class BASE_EXPORT CheckedObserverAdapter {
public:
explicit CheckedObserverAdapter(const CheckedObserver* observer);
CheckedObserverAdapter(CheckedObserverAdapter&& other);
CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
CheckedObserverAdapter(const CheckedObserverAdapter&) = delete;
CheckedObserverAdapter& operator=(const CheckedObserverAdapter&) = delete;
~CheckedObserverAdapter();
void MarkForRemoval() {
DCHECK(weak_ptr_);
weak_ptr_ = nullptr;
}
bool IsMarkedForRemoval() const {
CHECK(!weak_ptr_.WasInvalidated());
return weak_ptr_ == nullptr;
}
bool IsEqual(const CheckedObserver* rhs) const {
return weak_ptr_.get() == rhs;
}
template <class ObserverType>
static ObserverType* Get(const CheckedObserverAdapter& adapter) {
static_assert(
std::is_base_of<CheckedObserver, ObserverType>::value,
"Observers should inherit from base::CheckedObserver. "
"Use ObserverList<T>::Unchecked to observe with raw pointers.");
DCHECK(adapter.weak_ptr_);
return static_cast<ObserverType*>(adapter.weak_ptr_.get());
}
#if DCHECK_IS_ON()
std::string GetCreationStackString() const { return stack_.ToString(); }
#endif
private:
WeakPtr<CheckedObserver> weak_ptr_;
#if DCHECK_IS_ON()
base::debug::StackTrace stack_;
#endif
};
template <class ObserverList>
class WeakLinkNode : public base::LinkNode<WeakLinkNode<ObserverList>> {
public:
WeakLinkNode() = default;
explicit WeakLinkNode(ObserverList* list) { SetList(list); }
WeakLinkNode(const WeakLinkNode&) = delete;
WeakLinkNode& operator=(const WeakLinkNode&) = delete;
~WeakLinkNode() { Invalidate(); }
bool IsOnlyRemainingNode() const {
return list_ &&
list_->live_iterators_.head() == list_->live_iterators_.tail();
}
void SetList(ObserverList* list) {
DCHECK(!list_);
DCHECK(list);
list_ = list;
list_->live_iterators_.Append(this);
}
void Invalidate() {
if (list_) {
list_ = nullptr;
this->RemoveFromList();
}
}
ObserverList* get() const {
if (list_)
DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
return list_;
}
ObserverList* operator->() const { return get(); }
explicit operator bool() const { return get(); }
private:
RAW_PTR_EXCLUSION ObserverList* list_ = nullptr;
};
}
}
#endif