Skip to content

Commit

Permalink
add support for offset based serialization
Browse files Browse the repository at this point in the history
offset_ptr: stores the offset as difference between `this` and the object it points to
Serializing this allows to skip the deserialization step and just use a `reinterpret_cast<T>(buf.begin())`.
This is useful for example in situations with shared memory.
  • Loading branch information
felixguendling authored Dec 16, 2018
1 parent 1dd9c13 commit c829cd0
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 72 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ addons:
env:
- COVERAGE=Off BUILD_TYPE=Release LDFLAGS="-stdlib=libc++" CC="clang-7" CXX="clang++-7" CXXFLAGS="-std=c++17 -stdlib=libc++ -D_LIBCPP_VERSION=1"
- COVERAGE=Off BUILD_TYPE=Debug LDFLAGS="-stdlib=libc++" CC="clang-7" CXX="clang++-7" CXXFLAGS="-std=c++17 -stdlib=libc++ -D_LIBCPP_VERSION=1 -fno-omit-frame-pointer -fsanitize=address"
- COVERAGE=Off BUILD_TYPE=Release LDFLAGS="-stdlib=libc++" CC="clang-7" CXX="clang++-7" CXXFLAGS="-std=c++17 -stdlib=libc++ -D_LIBCPP_VERSION=1 -fno-omit-frame-pointer -fsanitize=address"
- COVERAGE=Off BUILD_TYPE=Release CC="gcc-7" CXX="g++-7" CXXFLAGS="-std=c++17"
- COVERAGE=Off BUILD_TYPE=Debug CC="gcc-7" CXX="g++-7" CXXFLAGS="-std=c++17 -fno-omit-frame-pointer -fsanitize=address"
- COVERAGE=On BUILD_TYPE=Debug CC="gcc-7" CXX="g++-7" CXXFLAGS="-std=c++17"
Expand Down
82 changes: 82 additions & 0 deletions include/cista/containers/offset_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma once

#include "cista/offset_t.h"

namespace cista {

template <typename T>
struct offset_ptr {
offset_ptr() = default;
offset_ptr(std::nullptr_t) : offset_{NULLPTR_OFFSET} {}
offset_ptr(T const* p) : offset_{ptr_to_offset(p)} {}

offset_ptr& operator=(T const* p) {
offset_ = ptr_to_offset(p);
return *this;
}
offset_ptr& operator=(std::nullptr_t) {
offset_ = NULLPTR_OFFSET;
return *this;
}

offset_ptr(offset_ptr const& o) : offset_ptr{o.get()} {}
offset_ptr(offset_ptr&& o) : offset_ptr{o.get()} {}
offset_ptr& operator=(offset_ptr const& o) {
offset_ = ptr_to_offset(o.get());
}
offset_ptr& operator=(offset_ptr&& o) { offset_ = ptr_to_offset(o.get()); }

offset_t ptr_to_offset(T const* p) const {
return p == nullptr
? NULLPTR_OFFSET
: static_cast<offset_t>(reinterpret_cast<uintptr_t>(p) -
reinterpret_cast<uintptr_t>(this));
}

operator T*() { return get(); }
operator T const*() const { return get(); }
T& operator*() { return *get(); }
T const& operator*() const { return *get(); }

T* operator->() { return get(); }
T const* operator->() const { return get(); }

T const* get() const {
auto const ptr = offset_ == NULLPTR_OFFSET
? nullptr
: reinterpret_cast<T const*>(
reinterpret_cast<uintptr_t>(this) + offset_);
return ptr;
}
T* get() {
auto const ptr =
offset_ == NULLPTR_OFFSET
? nullptr
: reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + offset_);
return ptr;
}

template <typename Int>
offset_ptr operator+(Int i) const {
offset_ptr r = *this;
r.offset_ += i * sizeof(T);
return r;
}

friend bool operator==(std::nullptr_t, offset_ptr const& o) {
return o.offset_ == NULLPTR_OFFSET;
}
friend bool operator==(offset_ptr const& o, std::nullptr_t) {
return o.offset_ == NULLPTR_OFFSET;
}
friend bool operator!=(std::nullptr_t, offset_ptr const& o) {
return o.offset_ != NULLPTR_OFFSET;
}
friend bool operator!=(offset_ptr const& o, std::nullptr_t) {
return o.offset_ != NULLPTR_OFFSET;
}

offset_t offset_;
};

} // namespace cista
54 changes: 35 additions & 19 deletions include/cista/containers/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <cstring>
#include <string_view>

#include "cista/containers/offset_ptr.h"

namespace cista {

struct string {
template <typename Ptr = char const*>
struct basic_string {
using msize_t = uint32_t;

static msize_t mstrlen(char const* s) {
Expand All @@ -18,26 +21,30 @@ struct string {
static constexpr struct non_owning_t {
} non_owning{};

string() { std::memset(this, 0, sizeof(*this)); }
~string() { reset(); }
basic_string() { std::memset(this, 0, sizeof(*this)); }
~basic_string() { reset(); }

string(char const* s, owning_t) : string() { set_owning(s, mstrlen(s)); }
string(char const* s, non_owning_t) : string() { set_non_owning(s); }
string(char const* s) : string(s, non_owning) {} // NOLINT
basic_string(char const* s, owning_t) : basic_string() {
set_owning(s, mstrlen(s));
}
basic_string(char const* s, non_owning_t) : basic_string() {
set_non_owning(s);
}
basic_string(char const* s) : basic_string(s, non_owning) {} // NOLINT

string(string const& s) : string() { copy_from(s); }
basic_string(basic_string const& s) : basic_string() { copy_from(s); }

string(string&& s) {
basic_string(basic_string&& s) {
std::memcpy(this, &s, sizeof(*this));
std::memset(&s, 0, sizeof(*this));
}

string& operator=(string const& s) {
basic_string& operator=(basic_string const& s) {
copy_from(s);
return *this;
}

string& operator=(string&& s) {
basic_string& operator=(basic_string&& s) {
std::memcpy(this, &s, sizeof(*this));
return *this;
}
Expand All @@ -46,7 +53,7 @@ struct string {

void reset() {
if (!h_.is_short_ && h_.ptr_ != nullptr && h_.self_allocated_) {
std::free(const_cast<char*>(h_.ptr_));
std::free(const_cast<char*>(data()));
}
std::memset(this, 0, sizeof(*this));
}
Expand All @@ -72,7 +79,7 @@ struct string {
}
h_.size_ = size;
h_.self_allocated_ = true;
std::memcpy(const_cast<char*>(h_.ptr_), str, size);
std::memcpy(const_cast<char*>(data()), str, size);
}
}

Expand All @@ -98,7 +105,7 @@ struct string {
h_.size_ = size;
}

void copy_from(string const& s) {
void copy_from(basic_string const& s) {
reset();
if (s.is_short()) {
std::memcpy(this, &s, sizeof(s));
Expand All @@ -111,18 +118,24 @@ struct string {

std::string_view view() const { return std::string_view{data(), size()}; }

char const* data() const { return is_short() ? s_.s_ : h_.ptr_; }
char const* data() const {
if constexpr (std::is_pointer_v<Ptr>) {
return is_short() ? s_.s_ : h_.ptr_;
} else {
return is_short() ? s_.s_ : h_.ptr_.get();
}
}

string& operator=(char const* s) {
basic_string& operator=(char const* s) {
set_non_owning(s, mstrlen(s));
return *this;
}

friend bool operator==(string const& a, char const* b) {
friend bool operator==(basic_string const& a, char const* b) {
return a.view() == std::string_view{b};
}

friend bool operator==(string const& a, string const& b) {
friend bool operator==(basic_string const& a, basic_string const& b) {
return a.view() == b.view();
}

Expand All @@ -145,7 +158,7 @@ struct string {
uint8_t __fill_2__{0};
uint8_t __fill_3__{0};
uint32_t size_{0};
char const* ptr_{nullptr};
Ptr ptr_{nullptr};
};

struct stack {
Expand All @@ -157,6 +170,9 @@ struct string {
heap h_;
stack s_;
};
};
}; // namespace cista

using string = basic_string<char const*>;
using o_string = basic_string<offset_ptr<char const>>;

} // namespace cista
25 changes: 19 additions & 6 deletions include/cista/containers/unique_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

#include <cinttypes>

#include "cista/containers/offset_ptr.h"

namespace cista {

template <typename T>
template <typename T, typename Ptr = T*>
struct unique_ptr {
using value_t = T;

Expand All @@ -31,24 +33,35 @@ struct unique_ptr {

~unique_ptr() {
if (self_allocated_ && el_ != nullptr) {
delete el_;
delete get();
}
}

T* get() const { return el_; }
T* get() { return el_; }
T const* get() const { return el_; }
T* operator->() { return el_; }
T& operator*() { return *el_; }
T const& operator*() const { return *el_; }
T const* operator->() const { return el_; }

T* el_{nullptr};
Ptr el_{nullptr};
bool self_allocated_{false};
uint8_t __fill_0__{0};
uint16_t __fill_1__{0};
uint32_t __fill_2__{0};
};

template <typename T>
using o_unique_ptr = unique_ptr<T, offset_ptr<T>>;

template <typename T, typename... Args>
unique_ptr<T> make_unique(Args&&... args) {
return unique_ptr<T>{new T{std::forward<Args>(args)...}, true};
}

template <typename T, typename... Args>
cista::unique_ptr<T> make_unique(Args&&... args) {
return cista::unique_ptr<T>{new T{std::forward<Args>(args)...}, true};
o_unique_ptr<T> make_o_unique(Args&&... args) {
return o_unique_ptr<T>{new T{std::forward<Args>(args)...}, true};
}

} // namespace cista
4 changes: 2 additions & 2 deletions include/cista/containers/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace cista {

template <typename T, typename TemplateSizeType = uint32_t>
template <typename T, typename Ptr = T*, typename TemplateSizeType = uint32_t>
struct vector {
using size_type = TemplateSizeType;
using value_type = T;
Expand Down Expand Up @@ -234,7 +234,7 @@ struct vector {

explicit operator std::string() const { return to_string(); }

T* el_{nullptr};
Ptr el_{nullptr};
TemplateSizeType used_size_{0};
TemplateSizeType allocated_size_{0};
bool self_allocated_{false};
Expand Down
4 changes: 3 additions & 1 deletion include/cista/offset_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace cista {

using offset_t = uint64_t;
using offset_t = int64_t;

constexpr auto const NULLPTR_OFFSET = std::numeric_limits<offset_t>::max();

} // namespace cista
Loading

0 comments on commit c829cd0

Please sign in to comment.