Skip to content

Commit

Permalink
Integrated an "uninitializedAllocator" which safely allows to create …
Browse files Browse the repository at this point in the history
…a std::vector (or similar data structure)

which can cheaply create new Elements (like ints) without initializing (zeroing) them.

This makes e.g. resizing the Vector to a bigger size much cheaper.
  • Loading branch information
joka921 committed Jul 16, 2021
1 parent 4308ec2 commit 73fe20a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/engine/IdTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@
#include "../global/Id.h"
#include "../util/AllocatorWithLimit.h"
#include "../util/Log.h"
#include "../util/UninitializedAllocator.h"

namespace detail {
// The actual data storage of the Id Tables, basically a wrapper around a
// std::vector<Id>
template <typename Allocator>
struct IdTableVectorWrapper {
static constexpr bool ManagesStorage = true; // is able to grow/allocate
std::vector<Id, Allocator> _data;

IdTableVectorWrapper(Allocator a) : _data{a} {};
using ActualAllocator = ad_utility::default_init_allocator<Id, Allocator>;
std::vector<Id, ActualAllocator> _data;

IdTableVectorWrapper(Allocator a) : _data{ActualAllocator{std::move(a)}} {};

// construct from c-style array by copying the content
explicit IdTableVectorWrapper(const Id* const ptr, size_t sz, Allocator a)
: _data{a} {
: _data{ActualAllocator{std::move(a)}} {
_data.assign(ptr, ptr + sz);
}

Expand Down
57 changes: 57 additions & 0 deletions src/util/UninitializedAllocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2021, University of Freiburg, Chair of Algorithms and Data Structures.
// Author: Johannes Kalmbach <kalmbacj@cs.uni-freiburg.de>

#ifndef QLEVER_UNINITIALIZEDALLOCATOR_H
#define QLEVER_UNINITIALIZEDALLOCATOR_H

namespace ad_utility {
// Allocator adaptor that interposes construct() calls to
// convert value initialization into default initialization.
// This makes a difference for builtin arithmetic types like int, which are zero after a value initialization and have an undefined value after default initialization. Using this allocator adapter for a std::vector<int> makes a growing resize O(oldSize) while it being O(newSize) with the zeroing value initialization.
// Source: https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
// Most functionality is inherited from the underlying allocator type A
template <typename T, typename A = std::allocator<T>>
class default_init_allocator : public A {
typedef std::allocator_traits<A> a_t;

public:

// This is needed for technical reasons.
template <typename U>
struct rebind {
using other =
default_init_allocator<U, typename a_t::template rebind_alloc<U>>;
};

// Inherit all constructors from the base allocator.
using A::A;

// "Copy" and "Move" construction from underlying type
default_init_allocator(const A& a) : A{a} {}
default_init_allocator(A&& a) : A{std::move(a)} {}
default_init_allocator(const default_init_allocator&) = default;
default_init_allocator(default_init_allocator&&) = default;
default_init_allocator& operator= (default_init_allocator&&) = default;
default_init_allocator& operator= (const default_init_allocator&) = default;

// overload the construct template with default initialization
template <typename U>
void construct(U* ptr) noexcept(
std::is_nothrow_default_constructible<U>::value) {
// new without parentheses after the type performs default-initialization
// see https://en.cppreference.com/w/cpp/language/new (paragraph "Construction")
::new (static_cast<void*>(ptr)) U;
}
// initialization with parameters, the actual construction is completely performed
// by the underlying allocator.
template <typename U, typename... Args>
void construct(U* ptr, Args&&... args) {
a_t::construct(static_cast<A&>(*this), ptr, std::forward<Args>(args)...);
}
};
} // namespace ad_utility




#endif // QLEVER_UNINITIALIZEDALLOCATOR_H

0 comments on commit 73fe20a

Please sign in to comment.