This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,5 @@
---
Checks: '>
clang-diagnostic-*,
'
...

63
node_modules/react-native/ReactCommon/utils/BUCK generated vendored Normal file
View File

@ -0,0 +1,63 @@
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode")
load(
"//tools/build_defs/oss:rn_defs.bzl",
"ANDROID",
"APPLE",
"CXX",
"get_apple_compiler_flags",
"get_apple_inspector_flags",
"react_native_xplat_target",
"rn_xplat_cxx_library",
"subdir_glob",
)
APPLE_COMPILER_FLAGS = get_apple_compiler_flags()
rn_xplat_cxx_library(
name = "utils",
srcs = glob(
[
"**/*.cpp",
"**/*.mm",
],
exclude = glob(["tests/**/*.cpp"]),
),
headers = glob(
["**/*.h"],
exclude = glob(["tests/**/*.h"]),
),
header_namespace = "",
exported_headers = subdir_glob(
[
("", "*.h"),
],
prefix = "react/utils",
),
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
fbobjc_frameworks = ["Foundation"],
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
force_static = True,
macosx_tests_override = [],
platforms = (ANDROID, APPLE, CXX),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
tests = [],
visibility = ["PUBLIC"],
deps = [
"//xplat/folly:container_evicting_cache_map",
"//xplat/folly:headers_only",
"//xplat/folly:memory",
"//xplat/folly:molly",
"//xplat/jsi:jsi",
react_native_xplat_target("better:better"),
],
)

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) Facebook, Inc. and its 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 <mutex>
#include <string>
#include <better/map.h>
#include <better/mutex.h>
#include <better/optional.h>
namespace facebook {
namespace react {
/*
* General purpose dependency injection container.
* Instance types must be copyable.
*/
class ContextContainer final {
public:
using Shared = std::shared_ptr<ContextContainer const>;
/*
* Registers an instance of the particular type `T` in the container
* using the provided `key`. Only one instance can be registered per key.
* The method does nothing if given `key` already exists in the container.
*
* Convention is to use the plain base class name for the key, so for
* example if the type `T` is `std::shared_ptr<const ReactNativeConfig>`,
* then one would use `"ReactNativeConfig"` for the `key`, even if the
* instance is actually a `shared_ptr` of derived class
*`EmptyReactNativeConfig`.
*/
template <typename T>
void insert(std::string const &key, T const &instance) const {
std::unique_lock<better::shared_mutex> lock(mutex_);
instances_.insert({key, std::make_shared<T>(instance)});
#ifndef NDEBUG
typeNames_.insert({key, typeid(T).name()});
#endif
}
/*
* Removes an instance stored for a given `key`.
* Does nothing if the instance was not found.
*/
void erase(std::string const &key) const {
std::unique_lock<better::shared_mutex> lock(mutex_);
instances_.erase(key);
#ifndef NDEBUG
typeNames_.erase(key);
#endif
}
/*
* Updates the container with values from a given container.
* Values with keys that already exist in the container will be replaced with
* values from the given container.
*/
void update(ContextContainer const &contextContainer) const {
std::unique_lock<better::shared_mutex> lock(mutex_);
for (auto const &pair : contextContainer.instances_) {
instances_.erase(pair.first);
instances_.insert(pair);
#ifndef NDEBUG
typeNames_.erase(pair.first);
typeNames_.insert(
{pair.first, contextContainer.typeNames_.at(pair.first)});
#endif
}
}
/*
* Returns a previously registered instance of the particular type `T`
* for `key`.
* Throws an exception if the instance could not be found.
*/
template <typename T>
T at(std::string const &key) const {
std::shared_lock<better::shared_mutex> lock(mutex_);
assert(
instances_.find(key) != instances_.end() &&
"ContextContainer doesn't have an instance for given key.");
assert(
typeNames_.at(key) == typeid(T).name() &&
"ContextContainer stores an instance of different type for given key.");
return *std::static_pointer_cast<T>(instances_.at(key));
}
/*
* Returns a (wrapped in an optional) previously registered instance of
* the particular type `T` for given `key`.
* Returns an empty optional if the instance could not be found.
*/
template <typename T>
better::optional<T> find(std::string const &key) const {
std::shared_lock<better::shared_mutex> lock(mutex_);
auto iterator = instances_.find(key);
if (iterator == instances_.end()) {
return {};
}
assert(
typeNames_.at(key) == typeid(T).name() &&
"ContextContainer stores an instance of different type for given key.");
return *std::static_pointer_cast<T>(iterator->second);
}
private:
mutable better::shared_mutex mutex_;
// Protected by mutex_`.
mutable better::map<std::string, std::shared_ptr<void>> instances_;
#ifndef NDEBUG
mutable better::map<std::string, std::string> typeNames_;
#endif
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) Facebook, Inc. and its 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
namespace facebook {
namespace react {
inline bool floatEquality(float a, float b, float epsilon = 0.005f) {
return (std::isnan(a) && std::isnan(b)) ||
(!std::isnan(a) && !std::isnan(b) && fabs(a - b) < epsilon);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) Facebook, Inc. and its 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
#if defined(__OBJC__) && defined(__cplusplus)
#if TARGET_OS_MAC && TARGET_OS_IPHONE
#include <memory>
#import <Foundation/Foundation.h>
@interface RCTInternalGenericWeakWrapper : NSObject
@property (nonatomic, weak) id object;
@end
namespace facebook {
namespace react {
/*
* `wrapManagedObject` and `unwrapManagedObject` are wrapper functions that
* convert ARC-managed objects into `std::shared_ptr<void>` and vice-versa. It's
* a very useful mechanism when we need to pass Objective-C objects through pure
* C++ code, pass blocks into C++ lambdas, and so on.
*
* The idea behind this mechanism is quite simple but tricky: When we
* instantiate a C++ shared pointer for a managed object, we practically call
* `CFRetain` for it once and then we represent this single retaining operation
* as a counter inside the shared pointer; when the counter became zero, we call
* `CFRelease` on the object. In this model, one bump of ARC-managed counter is
* represented as multiple bumps of C++ counter, so we can have multiple
* counters for the same object that form some kind of counters tree.
*/
inline std::shared_ptr<void> wrapManagedObject(id object)
{
return std::shared_ptr<void>((__bridge_retained void *)object, CFRelease);
}
inline id unwrapManagedObject(std::shared_ptr<void> const &object)
{
return (__bridge id)object.get();
}
inline std::shared_ptr<void> wrapManagedObjectWeakly(id object)
{
RCTInternalGenericWeakWrapper *weakWrapper = [RCTInternalGenericWeakWrapper new];
weakWrapper.object = object;
return wrapManagedObject(weakWrapper);
}
inline id unwrapManagedObjectWeakly(std::shared_ptr<void> const &object)
{
RCTInternalGenericWeakWrapper *weakWrapper = (RCTInternalGenericWeakWrapper *)unwrapManagedObject(object);
assert(weakWrapper && "`RCTInternalGenericWeakWrapper` instance must not be `nil`.");
return weakWrapper.object;
}
} // namespace react
} // namespace facebook
#endif
#endif

View File

@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ManagedObjectWrapper.h"
#if defined(__OBJC__) && defined(__cplusplus)
#if TARGET_OS_MAC && TARGET_OS_IPHONE
@implementation RCTInternalGenericWeakWrapper
@end
#endif
#endif

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) Facebook, Inc. and its 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 <mutex>
#include <thread>
#include <jsi/jsi.h>
namespace facebook {
namespace react {
/*
* Takes a function and calls it with a reference to a Runtime. The function
* will be called when it is safe to do so (i.e. it ensures non-concurrent
* access) and may be invoked asynchronously, depending on the implementation.
* If you need to access a Runtime, it's encouraged to use a RuntimeExecutor
* instead of storing a pointer to the Runtime itself, which makes it more
* difficult to ensure that the Runtime is being accessed safely.
*/
using RuntimeExecutor =
std::function<void(std::function<void(jsi::Runtime &runtime)> &&callback)>;
/*
* The caller can expect that the callback will be executed sometime later on an
* unspecified thread.
* Use this method when the caller prefers to not be blocked by executing the
* `callback`.
* Note that this method does not provide any guarantees
* about when the `callback` will be executed (before returning to the caller,
* after that, or in parallel), the only thing that is guaranteed is that there
* is no synchronization.
*/
inline static void executeAsynchronously(
RuntimeExecutor const &runtimeExecutor,
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
std::thread{[callback = std::move(callback), runtimeExecutor]() mutable {
runtimeExecutor(std::move(callback));
}};
}
/*
* Executes a `callback` in a *synchronous* manner using given
* `RuntimeExecutor`.
* Use this method when the caller needs to *be blocked* by executing the
* callback but does not concerted about the particular thread on which the
* `callback` will be executed.
*/
inline static void executeSynchronously_CAN_DEADLOCK(
RuntimeExecutor const &runtimeExecutor,
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
std::mutex mutex;
mutex.lock();
runtimeExecutor(
[callback = std::move(callback), &mutex](jsi::Runtime &runtime) {
callback(runtime);
mutex.unlock();
});
mutex.lock();
}
/*
* Executes a `callback` in a *synchronous* manner on the same thread using
* given `RuntimeExecutor`.
* Use this method when the caller needs to *be blocked* by executing the
* `callback` and requires that the callback will be executed on the same
* thread.
*/
inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
RuntimeExecutor const &runtimeExecutor,
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
// Note: We need the third mutex to get back to the main thread before
// the lambda is finished (because all mutexes are allocated on the stack).
// We use `recursive_mutex` here to not deadlock in case if a
// `RuntimeExecutor` executes the callback synchronously.
std::recursive_mutex mutex1;
std::recursive_mutex mutex2;
std::recursive_mutex mutex3;
mutex1.lock();
mutex2.lock();
mutex3.lock();
jsi::Runtime *runtimePtr;
runtimeExecutor([&](jsi::Runtime &runtime) {
runtimePtr = &runtime;
mutex1.unlock();
// `callback` is called somewhere here.
mutex2.lock();
mutex3.unlock();
});
mutex1.lock();
callback(*runtimePtr);
mutex2.unlock();
mutex3.lock();
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <functional>
#include <memory>
#include <mutex>
#include <better/mutex.h>
namespace facebook {
namespace react {
/*
* `SharedFunction` implements a pattern of a shared callable object that
* contains the same executable inside. It's similar to `std::function` with
* one important difference: when the object is copied, the stored function (and
* captured values) are shared between instances (not copied). `SharedFunction`
* can be stored inside `std::function` because it's callable. It useful in some
* scenarios, such as:
* - When captured by `std::function` arguments are not copyable;
* - When we need to replace the content of the callable later on the go.
*/
template <typename ReturnT = void, typename... ArgumentT>
class SharedFunction {
using T = ReturnT(ArgumentT...);
struct Pair {
Pair(std::function<T> &&function) : function(std::move(function)) {}
std::function<T> function;
better::shared_mutex mutex{};
};
public:
SharedFunction(std::function<T> &&function = nullptr)
: pair_(std::make_shared<Pair>(std::move(function))) {}
SharedFunction(const SharedFunction &other) = default;
SharedFunction(SharedFunction &&other) noexcept = default;
SharedFunction &operator=(const SharedFunction &other) = default;
SharedFunction &operator=(SharedFunction &&other) noexcept = default;
void assign(std::function<T> function) const {
std::unique_lock<better::shared_mutex> lock(pair_->mutex);
pair_->function = function;
}
ReturnT operator()(ArgumentT... args) const {
std::shared_lock<better::shared_mutex> lock(pair_->mutex);
return pair_->function(args...);
}
private:
std::shared_ptr<Pair> pair_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <functional>
#include <memory>
#include <mutex>
#include <better/optional.h>
#include <folly/container/EvictingCacheMap.h>
namespace facebook {
namespace react {
/*
* Simple thread-safe LRU cache.
*/
template <typename KeyT, typename ValueT, int maxSize>
class SimpleThreadSafeCache {
public:
SimpleThreadSafeCache() : map_{maxSize} {}
/*
* Returns a value from the map with a given key.
* If the value wasn't found in the cache, constructs the value using given
* generator function, stores it inside a cache and returns it.
* Can be called from any thread.
*/
ValueT get(const KeyT &key, std::function<ValueT(const KeyT &key)> generator)
const {
std::lock_guard<std::mutex> lock(mutex_);
auto iterator = map_.find(key);
if (iterator == map_.end()) {
auto value = generator(key);
map_.set(key, value);
return value;
}
return iterator->second;
}
/*
* Returns a value from the map with a given key.
* If the value wasn't found in the cache, returns empty optional.
* Can be called from any thread.
*/
better::optional<ValueT> get(const KeyT &key) const {
std::lock_guard<std::mutex> lock(mutex_);
auto iterator = map_.find(key);
if (iterator == map_.end()) {
return {};
}
return iterator->second;
}
/*
* Sets a key-value pair in the LRU cache.
* Can be called from any thread.
*/
void set(const KeyT &key, const ValueT &value) const {
std::lock_guard<std::mutex> lock(mutex_);
map_.set(std::move(key), std::move(value));
}
private:
mutable folly::EvictingCacheMap<KeyT, ValueT> map_;
mutable std::mutex mutex_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) Facebook, Inc. and its 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 <chrono>
namespace facebook {
namespace react {
/*
* Represents a monotonic clock suitable for measuring intervals.
*/
using TelemetryClock = std::chrono::steady_clock;
/*
* Represents a point in time satisfied the requirements of TelemetryClock.
*/
using TelemetryTimePoint = TelemetryClock::time_point;
/*
* Represents a time interval satisfied the requirements of TelemetryClock.
*/
using TelemetryDuration = std::chrono::nanoseconds;
/*
* Represents a time point which never happens.
*/
static TelemetryTimePoint const kTelemetryUndefinedTimePoint =
TelemetryTimePoint::max();
/*
* Returns a time point representing the current point in time.
*/
static inline TelemetryTimePoint telemetryTimePointNow() {
return TelemetryClock::now();
}
/*
* Returns a number of milliseconds that passed from some epoch starting time
* point to a given time point. The epoch starting time point is not specified
* but stays the same for an application run.
*/
static inline int64_t telemetryTimePointToMilliseconds(
TelemetryTimePoint timePoint) {
return std::chrono::duration_cast<std::chrono::milliseconds>(
timePoint - TelemetryTimePoint{})
.count();
}
/*
* Returns a number of milliseconds that represents the given duration object.
*/
static inline int64_t telemetryDurationToMilliseconds(
TelemetryDuration duration) {
return std::chrono::duration_cast<std::chrono::milliseconds>(duration)
.count();
}
} // namespace react
} // namespace facebook