1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #pragma once
9 
10 #include <atomic>
11 #include <functional>
12 #include <memory>
13 
14 namespace ABI48_0_0facebook {
15 namespace ABI48_0_0React {
16 
17 /*
18  * A cross-platform abstraction for observing a run loop life cycle.
19  */
20 class RunLoopObserver {
21  public:
22   using Unique = std::unique_ptr<RunLoopObserver const>;
23 
24   /*
25    * The concept of an owner.
26    * A run loop observer normally observes a run loop running on a different
27    * thread. That implies that this other thread (the run loop thread) will call
28    * methods of this class owned by some other thread. To make it safe, we need
29    * to ensure that at the moment of the calling the observer still exists. To
30    * do so, we use an owner object (a weak pointer) that must retain (possibly
31    * indirectly) the observer. The platform-specific code should convert the
32    * weak pointer (owner) to a strong one right before calling the observer,
33    * ensuring the safety of calling; right after the call, the strong pointer
34    * should be safely released.
35    *
36    * Note, in the case when the pointer to the actual owner will be available
37    * later, only after calling the constructor of the class, the caller can
38    * create a dummy pointer beforehand and then merge it (using
39    * `shared_ptr<X>(shared_ptr<Y> const &, X *)`) with the actual one (sharing
40    * the control block).
41    */
42   using Owner = std::shared_ptr<void const>;
43   using WeakOwner = std::weak_ptr<void const>;
44 
45   /*
46    * Run loop activity stages which run loop observers can be observe.
47    */
48   enum Activity : int32_t {
49     None = 0,
50     BeforeWaiting = 1 << 0,
51     AfterWaiting = 1 << 1,
52   };
53 
54   /*
55    * A delegate interface.
56    */
57   class Delegate {
58    public:
59     /*
60      * Called on every run loop tick at moments corresponding to requested
61      * activities.
62      *
63      * A platform-specific implementation guarantees that the owner pointer
64      * is retained during this call.
65      * Will be called on the thread associated with the run loop.
66      */
67     virtual void activityDidChange(Delegate const *delegate, Activity activity)
68         const noexcept = 0;
69 
70     virtual ~Delegate() noexcept = default;
71   };
72 
73   using Factory = std::function<std::unique_ptr<RunLoopObserver>(
74       Activity activities,
75       WeakOwner const &owner)>;
76 
77   /*
78    * Constructs a run loop observer.
79    */
80   RunLoopObserver(Activity activities, WeakOwner const &owner) noexcept;
81   virtual ~RunLoopObserver() noexcept = default;
82 
83   /*
84    * Sets the delegate.
85    * Must be called just once.
86    */
87   void setDelegate(Delegate const *delegate) const noexcept;
88 
89   /*
90    * Enables or disables run loop observing.
91    * It can be used to save CPU cycles during periods of time when observing
92    * is not required.
93    * A newly constructed run time observer is initially disabled.
94    */
95   void enable() const noexcept;
96   void disable() const noexcept;
97 
98   /*
99    * Returns true if called on a thread associated with the run loop.
100    * Must be implemented in subclasses.
101    */
102   virtual bool isOnRunLoopThread() const noexcept = 0;
103 
104   /*
105    * Returns an owner associated with the observer.
106    * It might be useful to ensure the safety of consequent asynchronous calls.
107    */
108   WeakOwner getOwner() const noexcept;
109 
110  protected:
111   /*
112    * Must be implemented in subclasses.
113    */
114   virtual void startObserving() const noexcept = 0;
115   virtual void stopObserving() const noexcept = 0;
116 
117   /*
118    * Called by subclasses to generate a call on a delegate.
119    */
120   void activityDidChange(Activity activity) const noexcept;
121 
122   Activity const activities_{};
123   WeakOwner const owner_;
124   mutable Delegate const *delegate_{nullptr};
125   mutable std::atomic<bool> enabled_{false};
126 };
127 
128 } // namespace ABI48_0_0React
129 } // namespace ABI48_0_0facebook
130