xref: /aosp_15_r20/external/cronet/base/scoped_observation_traits.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_SCOPED_OBSERVATION_TRAITS_H_
6 #define BASE_SCOPED_OBSERVATION_TRAITS_H_
7 
8 namespace base {
9 
10 // `ScopedObservationTraits` is used to control the behavior of
11 // `ScopedObservation` on sources without AddObserver()/RemoveObserver()
12 // methods.
13 //
14 // The implementation of `ScopedObservation<Source, Observer>` will look up the
15 // most specialized version of `ScopedObservationTraits<Source, Observer>` and
16 // use the corresponding `Traits::AddObserver` and `Traits::RemoveObserver`.
17 //
18 // The default specialization takes care of any Source that exposes
19 // `AddObserver(Observer*)` and `RemoveObserver(Observer*)` methods -- if that's
20 // the case, then `ScopedObservation<Source, Observer>` will work out of the
21 // box.
22 //
23 // However, if your `CustomSource` features custom method names -- say,
24 // `AddFoo(FooObserver*)` and `RemoveFoo(FooObserver*)`, then you'll have to
25 // define a new traits specialization like this:
26 //
27 // `custom_source.h`:
28 //    #include "base/scoped_observation_traits.h"
29 //
30 //    class FooObserver;
31 //    class CustomSource {
32 //     public:
33 //      void AddFoo(FooObserver*);
34 //      void RemoveFoo(FooObserver*);
35 //    };
36 //
37 //    namespace base {
38 //
39 //    template<>
40 //    struct ScopedObservationTraits<CustomSource, FooObserver> {
41 //      static void AddObserver(CustomSource* source,
42 //                              FooObserver* observer) {
43 //        source->AddFoo(observer);
44 //      }
45 //      static void RemoveObserver(CustomSource* source,
46 //                                 FooObserver* observer) {
47 //        source->RemoveFoo(observer);
48 //      }
49 //    };
50 //
51 //    }  // namespace base
52 //
53 // `some_important_file.cc`:
54 //    // Now this works out of the box.
55 //    base::ScopedObservation<CustomSource, FooObserver> obs...
56 //
57 
58 template <class Source, class Observer>
59 struct ScopedObservationTraits {
60   static_assert(
61       requires(Source& source, Observer* observer) {
62         source.AddObserver(observer);
63         source.RemoveObserver(observer);
64       },
65       "The given Source is missing "
66       "AddObserver(Observer*) and/or RemoveObserver(Observer*) "
67       "methods. Please provide a custom specialization of "
68       "ScopedObservationTraits<> for this Source/Observer pair.");
69 
AddObserverScopedObservationTraits70   static void AddObserver(Source* source, Observer* observer) {
71     source->AddObserver(observer);
72   }
RemoveObserverScopedObservationTraits73   static void RemoveObserver(Source* source, Observer* observer) {
74     source->RemoveObserver(observer);
75   }
76 };
77 
78 }  // namespace base
79 
80 #endif  // BASE_SCOPED_OBSERVATION_TRAITS_H_
81