/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <bitset> #include <vector> #include <glog/logging.h> #include <folly/ConstructorCallbackList.h> #include <folly/Function.h> #include <folly/Optional.h> #include <folly/ScopeGuard.h> #include <folly/io/async/DestructorCheck.h> #include <folly/small_vector.h> /** * Tooling that makes it easier to design observable objects and observers. */ namespace folly { /** * Interface for store of pointers to observers. */ template <typename Observer> class ObserverContainerStoreBase { … }; /** * Policy for ObserverContainerStore. * * Defines the udnerlying container type and the default size. */ template <unsigned int ReserveElements = 2> struct ObserverContainerStorePolicyDefault { … }; /** * Policy-based implementation of ObserverContainerStoreBase. */ template < typename Observer, typename Policy = ObserverContainerStorePolicyDefault<>> class ObserverContainerStore : public ObserverContainerStoreBase<Observer> { public: using Base = ObserverContainerStoreBase<Observer>; using InvokeWhileIteratingPolicy = typename Base::InvokeWhileIteratingPolicy; /** * Construct a new store, reserving as configured. */ ObserverContainerStore() { … } /** * Add an observer pointer to the store. * * @param observer Observer to add. * @return Whether observer was added (not already present). */ bool add(std::shared_ptr<Observer> observer) override { … } /** * Remove an observer pointer from the store. * * @param observer Observer to remove. * @return Whether observer found and removed from store. */ bool remove(std::shared_ptr<Observer> observer) override { … } /** * Get number of observers in store. * * If called while the store is being iterated, the returned value may not * reflect changes that occurred (e.g., observers added or removed) during * iteration. * * @return Number of observers in store. */ size_t size() const override { … } /** * Invoke function for each observer in the store. * * @param fn Function to call for each observer in store. * @param policy InvokeWhileIteratingPolicy policy. */ void invokeForEachObserver( folly::Function<void(typename Base::MaybeManagedObserverPointer&)>&& fn, const typename Base::InvokeWhileIteratingPolicy policy) noexcept override { … } using Base::invokeForEachObserver; private: using container_type = typename Policy::template container<std::shared_ptr<Observer>>; // The actual list of observers. container_type observers_; // Whether we are actively iterating through the list of observers. bool iterating_{false}; // If we are actively iterating, the corresponding InvokeWhileIteratingPolicy. folly::Optional<InvokeWhileIteratingPolicy> maybeCurrentIterationPolicy_; // Whether a removal or addition occurred while we iterating through the list. bool removalDuringIteration_{false}; }; /** * Policy for ObserverContainerBase. * * @tparam EventEnum Enum of events that observers can subscribe to. * Each event must have a unique integer value greater * than zero. * * @tparam BitsetSize Size of bitset, must be greater than or equal to the * number of events in EventEnum. */ template <typename EventEnum, size_t BitsetSize> struct ObserverContainerBasePolicyDefault { … }; /** * Base ObserverContainer and definition of Observers. */ template < typename ObserverInterface, typename Observed, typename ContainerPolicy> class ObserverContainerBase { … }; /** * Policy-based implementation of ObserverContainerBase. */ template < typename ObserverInterface, typename Observed, typename ContainerPolicy, typename StorePolicy = ObserverContainerStorePolicyDefault<>, std::size_t MaxConstructorCallbacks = 4> class ObserverContainer : public ObserverContainerBase< ObserverInterface, Observed, ContainerPolicy> { … }; } // namespace folly