From 6355dd4f4d54e7a7c3a25ebef81e9d543e183d09 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Wed, 30 Nov 2016 17:20:48 +0100 Subject: [PATCH] PtrInt data structure (Pointer Integer pair inside one pointer location). Part of T150 Summary: PtrInt data structure (Pointer Integer pair inside one pointer location). Part of T150 Test Plan: manual Reviewers: sale Subscribers: buda, sale Differential Revision: https://memgraph.phacility.com/D11 --- include/data_structures/ptr_int.hpp | 54 +++++++++++++++++++++++++++++ include/utils/numerics/log2.hpp | 10 ++++++ tests/unit/ptr_int.cpp | 20 +++++++++++ 3 files changed, 84 insertions(+) create mode 100644 include/data_structures/ptr_int.hpp create mode 100644 include/utils/numerics/log2.hpp create mode 100644 tests/unit/ptr_int.cpp diff --git a/include/data_structures/ptr_int.hpp b/include/data_structures/ptr_int.hpp new file mode 100644 index 000000000..9cf0ba709 --- /dev/null +++ b/include/data_structures/ptr_int.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include "utils/numerics/log2.hpp" + +template +struct PointerPackTraits +{ + // here is a place to embed something like platform specific things + // TODO: cover more cases + constexpr static int free_bits = utils::log2(alignof(PtrT)); + + static auto get_ptr(uintptr_t value) { return (PtrT)(value); } +}; + +template > +class PtrInt +{ +private: + constexpr static int int_shift = PtrTraits::free_bits - IntBits; + constexpr static uintptr_t ptr_mask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::free_bits) - 1); + constexpr static uintptr_t int_mask = + (uintptr_t)(((intptr_t)1 << IntBits) - 1); + + uintptr_t value {0}; + +public: + PtrInt(PtrT pointer, IntT integer) + { + set_ptr(pointer); + set_int(integer); + } + + auto set_ptr(PtrT pointer) + { + auto integer = static_cast(get_int()); + auto ptr = reinterpret_cast(pointer); + value = (ptr_mask & ptr) | (integer << int_shift); + } + + auto set_int(IntT integer) + { + auto ptr = reinterpret_cast(get_ptr()); + auto int_shifted = static_cast(integer << int_shift); + value = (int_mask & int_shifted) | ptr; + } + + auto get_ptr() const { return PtrTraits::get_ptr(value & ptr_mask); } + + auto get_int() const { return (IntT)((value >> int_shift) & int_mask); } +}; diff --git a/include/utils/numerics/log2.hpp b/include/utils/numerics/log2.hpp new file mode 100644 index 000000000..90e0a087e --- /dev/null +++ b/include/utils/numerics/log2.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace utils +{ + +constexpr size_t log2(size_t n) { return ((n < 2) ? 0 : 1 + log2(n >> 1)); } + +} diff --git a/tests/unit/ptr_int.cpp b/tests/unit/ptr_int.cpp new file mode 100644 index 000000000..a3589ae34 --- /dev/null +++ b/tests/unit/ptr_int.cpp @@ -0,0 +1,20 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#include "data_structures/ptr_int.hpp" + +TEST_CASE("Construct and read pointer integer pair type") +{ + auto ptr1 = std::make_unique(2); + PtrInt pack1(ptr1.get(), 1); + + REQUIRE(pack1.get_int() == 1); + REQUIRE(pack1.get_ptr() == ptr1.get()); + + + auto ptr2 = std::make_unique(2); + PtrInt pack2(ptr2.get(), 2); + + REQUIRE(pack2.get_int() == 2); + REQUIRE(pack2.get_ptr() == ptr2.get()); +}