/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include #include namespace facebook { namespace react { /* * A cross-platform abstraction for observing a run loop life cycle. */ class RunLoopObserver { public: using Unique = std::unique_ptr; /* * The concept of an owner. * A run loop observer normally observes a run loop running on a different * thread. That implies that this other thread (the run loop thread) will call * methods of this class owned by some other thread. To make it safe, we need * to ensure that at the moment of the calling the observer still exists. To * do so, we use an owner object (a weak pointer) that must retain (possibly * indirectly) the observer. The platform-specific code should convert the * weak pointer (owner) to a strong one right before calling the observer, * ensuring the safety of calling; right after the call, the strong pointer * should be safely released. * * Note, in the case when the pointer to the actual owner will be available * later, only after calling the constructor of the class, the caller can * create a dummy pointer beforehand and then merge it (using * `shared_ptr(shared_ptr const &, X *)`) with the actual one (sharing * the control block). */ using Owner = std::shared_ptr; using WeakOwner = std::weak_ptr; /* * Run loop activity stages which run loop observers can be observe. */ enum Activity : int32_t { None = 0, BeforeWaiting = 1 << 0, AfterWaiting = 1 << 1, }; /* * A delegate interface. */ class Delegate { public: /* * Called on every run loop tick at moments corresponding to requested * activities. * * A platform-specific implementation guarantees that the owner pointer * is retained during this call. * Will be called on the thread associated with the run loop. */ virtual void activityDidChange(Delegate const *delegate, Activity activity) const noexcept = 0; virtual ~Delegate() noexcept = default; }; using Factory = std::function( Activity activities, WeakOwner const &owner)>; /* * Constructs a run loop observer. */ RunLoopObserver(Activity activities, WeakOwner const &owner) noexcept; virtual ~RunLoopObserver() noexcept = default; /* * Sets the delegate. * Must be called just once. */ void setDelegate(Delegate const *delegate) const noexcept; /* * Enables or disables run loop observing. * It can be used to save CPU cycles during periods of time when observing * is not required. * A newly constructed run time observer is initially disabled. */ void enable() const noexcept; void disable() const noexcept; /* * Returns true if called on a thread associated with the run loop. * Must be implemented in subclasses. */ virtual bool isOnRunLoopThread() const noexcept = 0; /* * Returns an owner associated with the observer. * It might be useful to ensure the safety of consequent asynchronous calls. */ WeakOwner getOwner() const noexcept; protected: /* * Must be implemented in subclasses. */ virtual void startObserving() const noexcept = 0; virtual void stopObserving() const noexcept = 0; /* * Called by subclasses to generate a call on a delegate. */ void activityDidChange(Activity activity) const noexcept; Activity const activities_{}; WeakOwner const owner_; mutable Delegate const *delegate_{nullptr}; mutable std::atomic enabled_{false}; }; } // namespace react } // namespace facebook