folly/folly/ObserverContainer.h

/*
 * 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