211 lines
6.0 KiB
C
211 lines
6.0 KiB
C
|
/*
|
||
|
* 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 <memory>
|
||
|
#include <shared_mutex>
|
||
|
|
||
|
#include <react/renderer/core/LayoutConstraints.h>
|
||
|
#include <react/renderer/core/LayoutContext.h>
|
||
|
#include <react/renderer/core/ReactPrimitives.h>
|
||
|
#include <react/utils/ContextContainer.h>
|
||
|
|
||
|
namespace facebook {
|
||
|
namespace react {
|
||
|
|
||
|
class Scheduler;
|
||
|
class ShadowTree;
|
||
|
class MountingCoordinator;
|
||
|
class UIManager;
|
||
|
|
||
|
/*
|
||
|
* Represents a running React Native surface and provides control over it.
|
||
|
* The instances of this class are movable only.
|
||
|
* The instances of this class can be safely deallocated only if `status` is
|
||
|
* `Unregistered`; this is a way to enforce internal consistency and
|
||
|
* deallocation ordering constraints the core relies on.
|
||
|
*
|
||
|
*
|
||
|
* Even though all methods of the class are thread-safe, the consumer side must
|
||
|
* ensure the logical consistency of some methods (e.g. calling `stop` for
|
||
|
* non-running surface will crash).
|
||
|
*/
|
||
|
class SurfaceHandler {
|
||
|
public:
|
||
|
/*
|
||
|
* Represents a status of the `SurfaceHandler` instance.
|
||
|
*/
|
||
|
enum class Status {
|
||
|
/*
|
||
|
* Newly created, moved-from, or already-unregistered instances. The only
|
||
|
* state in which the object can be safely deallocated.
|
||
|
*/
|
||
|
Unregistered = 0,
|
||
|
|
||
|
/*
|
||
|
* Registered instances that have an internal reference to a `UIManager`
|
||
|
* instance and ready to start a surface.
|
||
|
*/
|
||
|
Registered = 1,
|
||
|
|
||
|
/*
|
||
|
* Registered and running instances.
|
||
|
*/
|
||
|
Running = 2,
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Can be constructed anytime with a `moduleName` and a `surfaceId`.
|
||
|
*/
|
||
|
SurfaceHandler(std::string const &moduleName, SurfaceId surfaceId) noexcept;
|
||
|
virtual ~SurfaceHandler() noexcept;
|
||
|
|
||
|
/*
|
||
|
* Movable-only.
|
||
|
*/
|
||
|
SurfaceHandler(SurfaceHandler &&other) noexcept;
|
||
|
SurfaceHandler(SurfaceHandler const &SurfaceHandler) noexcept = delete;
|
||
|
SurfaceHandler &operator=(SurfaceHandler &&other) noexcept;
|
||
|
SurfaceHandler &operator=(SurfaceHandler const &other) noexcept = delete;
|
||
|
|
||
|
#pragma mark - Surface Life-Cycle Management
|
||
|
|
||
|
/*
|
||
|
* Must be called before surface is started.
|
||
|
*/
|
||
|
void setContextContainer(
|
||
|
ContextContainer::Shared contextContainer) const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Returns a momentum value of the status.
|
||
|
*/
|
||
|
Status getStatus() const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Starts or stops the surface.
|
||
|
* Can not be called when the status is `Unregistered`.
|
||
|
* `start()` must not be called for a running surface, and `stop()` must not
|
||
|
* be called for a not running surface.
|
||
|
*/
|
||
|
void start() const noexcept;
|
||
|
void stop() const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Sets (and gets) the running mode.
|
||
|
* The running mode can be changed anytime (even for `Unregistered` surface).
|
||
|
*/
|
||
|
virtual void setDisplayMode(DisplayMode displayMode) const noexcept;
|
||
|
DisplayMode getDisplayMode() const noexcept;
|
||
|
|
||
|
#pragma mark - Accessors
|
||
|
|
||
|
SurfaceId getSurfaceId() const noexcept;
|
||
|
void setSurfaceId(SurfaceId surfaceId) const noexcept;
|
||
|
std::string getModuleName() const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Provides access for surface props.
|
||
|
* Props can be changed anytime (even for `Unregistered` surface).
|
||
|
*/
|
||
|
void setProps(folly::dynamic const &props) const noexcept;
|
||
|
folly::dynamic getProps() const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Returns a `MountingCoordinator` instance associated with a running surface.
|
||
|
* Can be not be called when the status is `Unregistered`.
|
||
|
* The returning value cannot be `nullptr`.
|
||
|
*/
|
||
|
std::shared_ptr<MountingCoordinator const> getMountingCoordinator()
|
||
|
const noexcept;
|
||
|
|
||
|
#pragma mark - Layout
|
||
|
|
||
|
/*
|
||
|
* Measures the surface with given layout constraints and layout context.
|
||
|
* Returns zero size if called on the stopped or unregistered surface.
|
||
|
*/
|
||
|
Size measure(
|
||
|
LayoutConstraints const &layoutConstraints,
|
||
|
LayoutContext const &layoutContext) const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Sets layout constraints and layout context for the surface.
|
||
|
*/
|
||
|
void constraintLayout(
|
||
|
LayoutConstraints const &layoutConstraints,
|
||
|
LayoutContext const &layoutContext) const noexcept;
|
||
|
|
||
|
/*
|
||
|
* Returns layout constraints and layout context associated with the surface.
|
||
|
*/
|
||
|
LayoutConstraints getLayoutConstraints() const noexcept;
|
||
|
LayoutContext getLayoutContext() const noexcept;
|
||
|
|
||
|
private:
|
||
|
friend class Scheduler;
|
||
|
|
||
|
/*
|
||
|
* Must be called by `Scheduler` during registration process.
|
||
|
*/
|
||
|
void setUIManager(UIManager const *uiManager) const noexcept;
|
||
|
|
||
|
void applyDisplayMode(DisplayMode displayMode) const noexcept;
|
||
|
|
||
|
#pragma mark - Link & Parameters
|
||
|
|
||
|
/*
|
||
|
* All data members of the class are split into two groups (`Link` and
|
||
|
* `Parameters`) that require separate synchronization. This way it's easier
|
||
|
* to see that proper lock is acquired. Separate synchronization is needed to
|
||
|
* prevent deadlocks.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Represents parameters of the surface. Parameters can be changed
|
||
|
* independently from controlling the running state
|
||
|
* (registering/unregistering, starting/stopping) of the surface.
|
||
|
* Changing parameters requires acquiring a unique lock; reading needs only
|
||
|
* a shared lock.
|
||
|
*/
|
||
|
struct Parameters {
|
||
|
std::string moduleName{};
|
||
|
SurfaceId surfaceId{};
|
||
|
DisplayMode displayMode{DisplayMode::Visible};
|
||
|
folly::dynamic props{};
|
||
|
LayoutConstraints layoutConstraints{};
|
||
|
LayoutContext layoutContext{};
|
||
|
ContextContainer::Shared contextContainer{};
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Represents an underlying link to a `ShadowTree` and an `UIManager`.
|
||
|
* Registering, unregistering, starting, and stopping the surface requires
|
||
|
* acquiring a unique lock; other access needs only a shared lock.
|
||
|
*/
|
||
|
struct Link {
|
||
|
Status status{Status::Unregistered};
|
||
|
UIManager const *uiManager{};
|
||
|
ShadowTree const *shadowTree{};
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* `link_` and `linkMutex_` pair.
|
||
|
*/
|
||
|
mutable std::shared_mutex linkMutex_;
|
||
|
mutable Link link_;
|
||
|
|
||
|
/*
|
||
|
* `parameters_` and `parametersMutex_` pair.
|
||
|
*/
|
||
|
mutable std::shared_mutex parametersMutex_;
|
||
|
mutable Parameters parameters_;
|
||
|
};
|
||
|
|
||
|
} // namespace react
|
||
|
} // namespace facebook
|