
#ifndef PLS_ALIGNMENT_H
#define PLS_ALIGNMENT_H

#include <cstdint>
#include <cstdlib>

#include "system_details.h"

namespace pls {
namespace internal {
namespace base {
namespace alignment {

template<typename T>
struct aligned_wrapper {
  alignas(system_details::CACHE_LINE_SIZE) unsigned char data[sizeof(T)];
  T *pointer() { return reinterpret_cast<T *>(data); }
};
void *allocate_aligned(size_t size);

system_details::pointer_t next_alignment(system_details::pointer_t size);
system_details::pointer_t previous_alignment(system_details::pointer_t size);
char *next_alignment(char *pointer);

}

template<typename T>
struct aligned_aba_pointer {
  const system_details::pointer_t pointer_;

  explicit aligned_aba_pointer(T *pointer, unsigned int aba = 0) : pointer_{
      reinterpret_cast<system_details::pointer_t >(pointer) + aba} {}

  T *pointer() const {
    return reinterpret_cast<T *>(pointer_ & system_details::CACHE_LINE_ADDRESS_USED_BITS);
  }

  unsigned int aba() const {
    return pointer_ & system_details::CACHE_LINE_ADDRESS_UNUSED_BITS;
  }

  aligned_aba_pointer set_aba(unsigned int aba) const {
    return aligned_aba_pointer(pointer(), aba);
  }
};

}
}
}

#endif //PLS_ALIGNMENT_H
