#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#ifndef BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_
#define BASE_ALLOCATOR_DISPATCHER_INITIALIZER_H_
#include <tuple>
#include <utility>
#include "base/allocator/dispatcher/configuration.h"
#include "base/allocator/dispatcher/dispatcher.h"
#include "base/allocator/dispatcher/internal/tools.h"
namespace base::allocator::dispatcher {
namespace internal {
template <size_t CurrentIndex,
typename DispatcherType,
typename CheckObserverPredicate,
typename VerifiedObservers,
typename UnverifiedObservers,
size_t... IndicesToSelect>
inline void DoInitialize(DispatcherType& dispatcher,
CheckObserverPredicate check_observer,
const VerifiedObservers& verified_observers,
const UnverifiedObservers& unverified_observers,
std::index_sequence<IndicesToSelect...> indices) {
if constexpr (CurrentIndex < std::tuple_size_v<UnverifiedObservers>) {
if (check_observer(std::get<CurrentIndex>(unverified_observers))) {
DoInitialize<CurrentIndex + 1>(
dispatcher, check_observer, verified_observers, unverified_observers,
std::index_sequence<IndicesToSelect..., CurrentIndex>{});
} else {
DoInitialize<CurrentIndex + 1>(dispatcher, check_observer,
verified_observers, unverified_observers,
indices);
}
} else if constexpr (CurrentIndex == std::tuple_size_v<UnverifiedObservers>) {
auto observers = std::tuple_cat(
verified_observers,
std::make_tuple(std::get<IndicesToSelect>(unverified_observers)...));
static_assert(std::tuple_size_v<decltype(observers)> <=
configuration::kMaximumNumberOfObservers);
static_assert(sizeof...(IndicesToSelect) <=
configuration::kMaximumNumberOfOptionalObservers);
dispatcher.Initialize(std::move(observers));
}
}
}
template <typename... tuples>
using TupleCat = decltype(std::tuple_cat(std::declval<tuples>()...));
template <typename MandatoryObservers = std::tuple<>,
typename OptionalObservers = std::tuple<>>
struct BASE_EXPORT Initializer {
Initializer() = default;
Initializer(MandatoryObservers mandatory_observers,
OptionalObservers optional_observers)
: mandatory_observers_(std::move(mandatory_observers)),
optional_observers_(std::move(optional_observers)) {}
template <typename... NewMandatoryObservers,
std::enable_if_t<
internal::LessEqual((sizeof...(NewMandatoryObservers) +
std::tuple_size_v<OptionalObservers>),
configuration::kMaximumNumberOfObservers),
bool> = true>
Initializer<std::tuple<NewMandatoryObservers*...>, OptionalObservers>
SetMandatoryObservers(NewMandatoryObservers*... mandatory_observers) const {
return {std::make_tuple(mandatory_observers...), GetOptionalObservers()};
}
template <typename... AdditionalMandatoryObservers,
std::enable_if_t<internal::LessEqual(
std::tuple_size_v<MandatoryObservers> +
sizeof...(AdditionalMandatoryObservers) +
std::tuple_size_v<OptionalObservers>,
configuration::kMaximumNumberOfObservers),
bool> = true>
Initializer<TupleCat<MandatoryObservers,
std::tuple<AdditionalMandatoryObservers*...>>,
OptionalObservers>
AddMandatoryObservers(
AdditionalMandatoryObservers*... additional_mandatory_observers) const {
return {std::tuple_cat(GetMandatoryObservers(),
std::make_tuple(additional_mandatory_observers...)),
GetOptionalObservers()};
}
template <
typename... NewOptionalObservers,
std::enable_if_t<
internal::LessEqual(
sizeof...(NewOptionalObservers),
configuration::kMaximumNumberOfOptionalObservers) &&
internal::LessEqual((sizeof...(NewOptionalObservers) +
std::tuple_size_v<MandatoryObservers>),
configuration::kMaximumNumberOfObservers),
bool> = true>
Initializer<MandatoryObservers, std::tuple<NewOptionalObservers*...>>
SetOptionalObservers(NewOptionalObservers*... optional_observers) const {
return {GetMandatoryObservers(), std::make_tuple(optional_observers...)};
}
template <
typename... AdditionalOptionalObservers,
std::enable_if_t<
internal::LessEqual(
std::tuple_size_v<OptionalObservers> +
sizeof...(AdditionalOptionalObservers),
configuration::kMaximumNumberOfOptionalObservers) &&
internal::LessEqual((std::tuple_size_v<OptionalObservers> +
sizeof...(AdditionalOptionalObservers) +
std::tuple_size_v<MandatoryObservers>),
configuration::kMaximumNumberOfObservers),
bool> = true>
Initializer<
MandatoryObservers,
TupleCat<OptionalObservers, std::tuple<AdditionalOptionalObservers*...>>>
AddOptionalObservers(
AdditionalOptionalObservers*... additional_optional_observers) const {
return {GetMandatoryObservers(),
std::tuple_cat(GetOptionalObservers(),
std::make_tuple(additional_optional_observers...))};
}
template <typename DispatcherType>
void DoInitialize(DispatcherType& dispatcher) const {
internal::DoInitialize<0>(dispatcher, internal::IsValidObserver{},
GetMandatoryObservers(), GetOptionalObservers(),
{});
}
const MandatoryObservers& GetMandatoryObservers() const {
return mandatory_observers_;
}
const OptionalObservers& GetOptionalObservers() const {
return optional_observers_;
}
private:
MandatoryObservers mandatory_observers_;
OptionalObservers optional_observers_;
};
inline Initializer<> CreateInitializer() {
return {};
}
}
#endif