#ifndef _TILE_BASE_ALIGN_H
#define _TILE_BASE_ALIGN_H

#pragma once
#include <cstddef>

namespace tile {
constexpr std::size_t max_align_v = alignof(max_align_t);

#if defined(__x86_64__) || defined(__i386__)

// On Sandy Bridge, accessing adjacent cache lines also see destructive
// interference.
//
// @sa: https://github.com/facebook/folly/blob/master/folly/lang/Align.h
//
// Update at 20201124: Well, AMD's Zen 3 does the same.
constexpr std::size_t hardware_destructive_interference_size  = 128;
constexpr std::size_t hardware_constructive_interference_size = 64;

#elif defined(__powerpc64__)

// These values are read from
// `/sys/devices/system/cpu/cpu0/cache/index*/coherency_line_size`
constexpr std::size_t hardware_destructive_interference_size  = 128;
constexpr std::size_t hardware_constructive_interference_size = 128;

#elif defined(__ARM_ARCH_5T__)

constexpr std::size_t hardware_destructive_interference_size  = 32;
constexpr std::size_t hardware_constructive_interference_size = 32;

#elif defined(__arm__)
// Cache line sizes for ARM: These values are not strictly correct since
// cache line sizes depend on implementations, not architectures.  There
// are even implementations with cache line sizes configurable at boot
// time.

constexpr std::size_t hardware_destructive_interference_size  = 64;
constexpr std::size_t hardware_constructive_interference_size = 64;

#elif defined(__aarch64__)

// AArch64 is ... weird, to say the least. Some vender (notably Samsung) uses a
// non-consistent cacheline size across BIG / little cores..
//
// Let's ignore those CPUs for now.
//
// @sa: https://www.mono-project.com/news/2016/09/12/arm64-icache/
constexpr std::size_t hardware_destructive_interference_size  = 64;
constexpr std::size_t hardware_constructive_interference_size = 64;

#else

constexpr std::size_t hardware_constructive_interference_size = max_align_v;
constexpr std::size_t hardware_destructive_interference_size  = max_align_v;
// #error Unsupported architecture.
// #pragma message("Unsupported architecture, use max_align_v")

#endif
static_assert(hardware_constructive_interference_size >= max_align_v,
              "hardware constructive interference size is too small");
static_assert(hardware_destructive_interference_size >= max_align_v,
              "hardware destructive interference size is too small");
}// namespace tile

#endif// _TILE_BASE_ALIGN_H
