diff --git a/yoga/event/event.cpp b/yoga/event/event.cpp index e2fe3588..02e70dce 100644 --- a/yoga/event/event.cpp +++ b/yoga/event/event.cpp @@ -5,51 +5,57 @@ * file in the root directory of this source tree. */ #include "event.h" +#include #include #include -#include - -#include namespace facebook { namespace yoga { namespace { -std::mutex& eventSubscribersMutex() { - static std::mutex subscribersMutex; - return subscribersMutex; -} +struct Node { + std::function subscriber = nullptr; + Node* next = nullptr; -std::shared_ptr& eventSubscribers() { - static auto subscribers = std::make_shared(); - return subscribers; + Node(std::function&& subscriber) + : subscriber{std::move(subscriber)} {} +}; + +std::atomic subscribers{nullptr}; + +Node* push(Node* newHead) { + Node* oldHead; + do { + oldHead = subscribers.load(std::memory_order_relaxed); + if (newHead != nullptr) { + newHead->next = oldHead; + } + } while (!subscribers.compare_exchange_weak( + oldHead, newHead, std::memory_order_release, std::memory_order_relaxed)); + return oldHead; } } // namespace void Event::reset() { - eventSubscribers() = std::make_shared(); + auto head = push(nullptr); + while (head != nullptr) { + auto current = head; + head = head->next; + delete current; + } } void Event::subscribe(std::function&& subscriber) { - std::lock_guard guard(eventSubscribersMutex()); - eventSubscribers() = - std::make_shared(*eventSubscribers()); - eventSubscribers()->push_back(subscriber); + push(new Node{std::move(subscriber)}); } void Event::publish(const YGNode& node, Type eventType, const Data& eventData) { - std::shared_ptr subscribers; - { - std::lock_guard guard(eventSubscribersMutex()); - subscribers = eventSubscribers(); - } - - for (auto& subscriber : *subscribers) { - if (subscriber) { - subscriber(node, eventType, eventData); - } + for (auto subscriber = subscribers.load(std::memory_order_relaxed); + subscriber != nullptr; + subscriber = subscriber->next) { + subscriber->subscriber(node, eventType, eventData); } }