jiuyiUniapp/service/node_modules/react-native/ReactCommon/react/bridging/EventEmitter.h

135 lines
4.1 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 <react/bridging/Function.h>
#include <functional>
#include <memory>
#include <mutex>
#include <unordered_map>
#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test
namespace facebook::react {
class EventSubscription {
public:
explicit EventSubscription(std::function<void()> remove)
: remove_(std::move(remove)) {}
~EventSubscription() = default;
EventSubscription(EventSubscription&&) noexcept = default;
EventSubscription& operator=(EventSubscription&&) noexcept = default;
EventSubscription(const EventSubscription&) = delete;
EventSubscription& operator=(const EventSubscription&) = delete;
private:
friend Bridging<EventSubscription>;
std::function<void()> remove_;
};
template <>
struct Bridging<EventSubscription> {
static jsi::Object toJs(
jsi::Runtime& rt,
const EventSubscription& eventSubscription,
const std::shared_ptr<CallInvoker>& jsInvoker) {
auto result = jsi::Object(rt);
result.setProperty(
rt, "remove", bridging::toJs(rt, eventSubscription.remove_, jsInvoker));
return result;
}
};
class IAsyncEventEmitter {
public:
IAsyncEventEmitter() noexcept = default;
virtual ~IAsyncEventEmitter() noexcept = default;
IAsyncEventEmitter(IAsyncEventEmitter&&) noexcept = default;
IAsyncEventEmitter& operator=(IAsyncEventEmitter&&) noexcept = default;
IAsyncEventEmitter(const IAsyncEventEmitter&) = delete;
IAsyncEventEmitter& operator=(const IAsyncEventEmitter&) = delete;
virtual jsi::Object get(
jsi::Runtime& rt,
const std::shared_ptr<CallInvoker>& jsInvoker) const = 0;
};
template <typename... Args>
class AsyncEventEmitter : public IAsyncEventEmitter {
static_assert(
sizeof...(Args) <= 1,
"AsyncEventEmitter must have at most one argument");
public:
AsyncEventEmitter() : state_(std::make_shared<SharedState>()) {
listen_ = [state = state_](AsyncCallback<Args...> listener) {
std::lock_guard<std::mutex> lock(state->mutex);
auto listenerId = state->listenerId++;
state->listeners.emplace(listenerId, std::move(listener));
return EventSubscription([state, listenerId]() {
std::lock_guard<std::mutex> innerLock(state->mutex);
state->listeners.erase(listenerId);
});
};
}
~AsyncEventEmitter() override = default;
AsyncEventEmitter(AsyncEventEmitter&&) noexcept = default;
AsyncEventEmitter& operator=(AsyncEventEmitter&&) noexcept = default;
AsyncEventEmitter(const AsyncEventEmitter&) = delete;
AsyncEventEmitter& operator=(const AsyncEventEmitter&) = delete;
void emit(std::function<jsi::Value(jsi::Runtime&)>&& converter) {
std::lock_guard<std::mutex> lock(state_->mutex);
for (auto& [_, listener] : state_->listeners) {
listener.call([converter](jsi::Runtime& rt, jsi::Function& jsFunction) {
jsFunction.call(rt, converter(rt));
});
}
}
void emit(Args... value) {
std::lock_guard<std::mutex> lock(state_->mutex);
for (const auto& [_, listener] : state_->listeners) {
listener.call(static_cast<Args>(value)...);
}
}
jsi::Object get(
jsi::Runtime& rt,
const std::shared_ptr<CallInvoker>& jsInvoker) const override {
return bridging::toJs(rt, listen_, jsInvoker);
}
private:
friend Bridging<AsyncEventEmitter>;
FRIEND_TEST(BridgingTest, eventEmitterTest);
struct SharedState {
std::mutex mutex;
std::unordered_map<size_t, AsyncCallback<Args...>> listeners;
size_t listenerId{};
};
std::function<EventSubscription(AsyncCallback<Args...>)> listen_;
std::shared_ptr<SharedState> state_;
};
template <typename... Args>
struct Bridging<AsyncEventEmitter<Args...>> {
static jsi::Object toJs(
jsi::Runtime& rt,
const AsyncEventEmitter<Args...>& eventEmitter,
const std::shared_ptr<CallInvoker>& jsInvoker) {
return eventEmitter.get(rt, jsInvoker);
}
};
} // namespace facebook::react