scoped_observation.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_SCOPED_OBSERVATION_H_
  5. #define BASE_SCOPED_OBSERVATION_H_
  6. #include <stddef.h>
  7. #include "base/check.h"
  8. #include "base/check_op.h"
  9. #include "base/memory/raw_ptr.h"
  10. namespace base {
  11. // ScopedObservation is used to keep track of singular observation, e.g.
  12. // where an observer observes a single source only.
  13. //
  14. // Use base::ScopedMultiSourceObservation for objects that observe multiple
  15. // sources.
  16. //
  17. // When ScopedObservation is destroyed, it removes the registered observation,
  18. // if any. Basic example (as a member variable):
  19. //
  20. // class MyFooObserver : public FooObserver {
  21. // ...
  22. // private:
  23. // ScopedObservation<Foo, FooObserver> foo_observation_{this};
  24. // };
  25. //
  26. // MyFooObserver::MyFooObserver(Foo* foo) {
  27. // foo_observation_.Observe(foo);
  28. // }
  29. //
  30. // For cases with methods not named AddObserver/RemoveObserver:
  31. //
  32. // class MyFooStateObserver : public FooStateObserver {
  33. // ...
  34. // private:
  35. // ScopedObservation<Foo,
  36. // FooStateObserver,
  37. // &Foo::AddStateObserver,
  38. // &Foo::RemoveStateObserver>
  39. // foo_observation_{this};
  40. // };
  41. template <class Source,
  42. class Observer,
  43. void (Source::*AddObsFn)(Observer*) = &Source::AddObserver,
  44. void (Source::*RemoveObsFn)(Observer*) = &Source::RemoveObserver>
  45. class ScopedObservation {
  46. public:
  47. explicit ScopedObservation(Observer* observer) : observer_(observer) {}
  48. ScopedObservation(const ScopedObservation&) = delete;
  49. ScopedObservation& operator=(const ScopedObservation&) = delete;
  50. ~ScopedObservation() { Reset(); }
  51. // Adds the object passed to the constructor as an observer on |source|.
  52. // IsObserving() must be false.
  53. void Observe(Source* source) {
  54. // TODO(https://crbug.com/1145565): Make this a DCHECK once ScopedObserver
  55. // has been fully retired.
  56. CHECK_EQ(source_, nullptr);
  57. source_ = source;
  58. (source_.get()->*AddObsFn)(observer_);
  59. }
  60. // Remove the object passed to the constructor as an observer from |source_|
  61. // if currently observing. Does nothing otherwise.
  62. void Reset() {
  63. if (source_) {
  64. (source_.get()->*RemoveObsFn)(observer_);
  65. source_ = nullptr;
  66. }
  67. }
  68. // Returns true if any source is being observed.
  69. bool IsObserving() const { return source_ != nullptr; }
  70. // Returns true if |source| is being observed.
  71. bool IsObservingSource(Source* source) const {
  72. DCHECK(source);
  73. return source_ == source;
  74. }
  75. private:
  76. const raw_ptr<Observer> observer_;
  77. // The observed source, if any.
  78. raw_ptr<Source> source_ = nullptr;
  79. };
  80. } // namespace base
  81. #endif // BASE_SCOPED_OBSERVATION_H_