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