#pragma once #include // std::forward, std::integer_sequence #include // std::size_t #include // std::hardware_destructive_interference_size #include // std::is_trivially_copyable #include "libipc/platform/detail.h" namespace ipc { template constexpr decltype(auto) static_switch(std::size_t /*i*/, std::index_sequence<>, F&& /*f*/, D&& def) { return std::forward(def)(); } template constexpr decltype(auto) static_switch(std::size_t i, std::index_sequence, F&& f, D&& def) { return (i == N) ? std::forward(f)(std::integral_constant{}) : static_switch(i, std::index_sequence{}, std::forward(f), std::forward(def)); } template constexpr decltype(auto) static_switch(std::size_t i, F&& f, D&& def) { return static_switch(i, std::make_index_sequence{}, std::forward(f), std::forward(def)); } template IPC_CONSTEXPR_ void static_for(std::index_sequence, F&& f) { IPC_UNUSED_ auto expand = { (std::forward(f)(std::integral_constant{}), 0)... }; } template IPC_CONSTEXPR_ void static_for(F&& f) { static_for(std::make_index_sequence{}, std::forward(f)); } // Minimum offset between two objects to avoid false sharing. enum { // #if __cplusplus >= 201703L // cache_line_size = std::hardware_destructive_interference_size // #else /*__cplusplus < 201703L*/ cache_line_size = 64 // #endif/*__cplusplus < 201703L*/ }; template auto horrible_cast(U rhs) noexcept -> typename std::enable_if::value && std::is_trivially_copyable::value, T>::type { union { T t; U u; } r = {}; r.u = rhs; return r.t; } IPC_CONSTEXPR_ std::size_t make_align(std::size_t align, std::size_t size) { // align must be 2^n return (size + align - 1) & ~(align - 1); } } // namespace ipc