Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions libcuckoo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ set (libcuckoo_VERSION "${libcuckoo_VERSION}.${libcuckoo_VERSION_PATCH}")
add_library(libcuckoo INTERFACE)
add_library(libcuckoo::libcuckoo ALIAS libcuckoo)

# tag libcuckoo target with a c++11 feature so that libcuckoo users
# will have c++11 turned on in their compile when they use this target.
# XXX: newer cmakes have a "cxx_std_11" feature that could be used
target_compile_features (libcuckoo INTERFACE cxx_constexpr)
# Require C++17 for std::byte, [[nodiscard]], and other modern features
target_compile_features (libcuckoo INTERFACE cxx_std_17)

# Include relative to the base directory
target_include_directories(libcuckoo INTERFACE
Expand Down
31 changes: 18 additions & 13 deletions libcuckoo/bucket_container.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <cstddef>
#include <iostream>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -60,11 +61,12 @@ public:
bucket() noexcept : occupied_() {}

const value_type &kvpair(size_type ind) const {
return *static_cast<const value_type *>(
static_cast<const void *>(&values_[ind]));
return *std::launder(
reinterpret_cast<const value_type *>(values_[ind]));
}
value_type &kvpair(size_type ind) {
return *static_cast<value_type *>(static_cast<void *>(&values_[ind]));
return *std::launder(
reinterpret_cast<value_type *>(values_[ind]));
}

const key_type &key(size_type ind) const {
Expand All @@ -90,19 +92,22 @@ public:

using storage_value_type = std::pair<Key, T>;

// Access a constructed key-value pair. Only valid when occupied(ind).
const storage_value_type &storage_kvpair(size_type ind) const {
return *static_cast<const storage_value_type *>(
static_cast<const void *>(&values_[ind]));
return *std::launder(
reinterpret_cast<const storage_value_type *>(values_[ind]));
}
storage_value_type &storage_kvpair(size_type ind) {
return *static_cast<storage_value_type *>(
static_cast<void *>(&values_[ind]));
return *std::launder(
reinterpret_cast<storage_value_type *>(values_[ind]));
}
// Raw pointer to uninitialized storage for construct/destroy.
storage_value_type *storage_ptr(size_type ind) {
return reinterpret_cast<storage_value_type *>(values_[ind]);
}

std::array<typename std::aligned_storage<sizeof(storage_value_type),
alignof(storage_value_type)>::type,
SLOT_PER_BUCKET>
values_;
alignas(storage_value_type)
std::byte values_[SLOT_PER_BUCKET][sizeof(storage_value_type)];
std::array<partial_t, SLOT_PER_BUCKET> partials_;
std::array<bool, SLOT_PER_BUCKET> occupied_;
};
Expand Down Expand Up @@ -201,7 +206,7 @@ public:
bucket &b = buckets_[ind];
assert(!b.occupied(slot));
b.partial(slot) = p;
traits_::construct(allocator_, std::addressof(b.storage_kvpair(slot)),
traits_::construct(allocator_, b.storage_ptr(slot),
std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...));
Expand All @@ -214,7 +219,7 @@ public:
bucket &b = buckets_[ind];
assert(b.occupied(slot));
b.occupied(slot) = false;
traits_::destroy(allocator_, std::addressof(b.storage_kvpair(slot)));
traits_::destroy(allocator_, b.storage_ptr(slot));
}

// Destroys all the live data in the buckets. Does not deallocate the bucket
Expand Down
27 changes: 14 additions & 13 deletions libcuckoo/cuckoohash_map.hh
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ public:
* @param equal equality function instance to use
* @param alloc allocator instance to use
*/
cuckoohash_map(size_type n = DEFAULT_SIZE, const Hash &hf = Hash(),
const KeyEqual &equal = KeyEqual(),
const Allocator &alloc = Allocator())
explicit cuckoohash_map(size_type n = DEFAULT_SIZE,
const Hash &hf = Hash(),
const KeyEqual &equal = KeyEqual(),
const Allocator &alloc = Allocator())
: hash_fn_(hf), eq_fn_(equal), buckets_(reserve_calc(n), alloc),
old_buckets_(0, alloc), all_locks_(get_allocator()),
num_remaining_lazy_rehash_locks_(0),
Expand Down Expand Up @@ -287,50 +288,50 @@ public:
*
* @return the hash function
*/
hasher hash_function() const { return hash_fn_; }
[[nodiscard]] hasher hash_function() const { return hash_fn_; }

/**
* Returns the function that compares keys for equality
*
* @return the key comparison function
*/
key_equal key_eq() const { return eq_fn_; }
[[nodiscard]] key_equal key_eq() const { return eq_fn_; }

/**
* Returns the allocator associated with the map
*
* @return the associated allocator
*/
allocator_type get_allocator() const { return buckets_.get_allocator(); }
[[nodiscard]] allocator_type get_allocator() const { return buckets_.get_allocator(); }

/**
* Returns the hashpower of the table, which is log<SUB>2</SUB>(@ref
* bucket_count()).
*
* @return the hashpower
*/
size_type hashpower() const { return buckets_.hashpower(); }
[[nodiscard]] size_type hashpower() const { return buckets_.hashpower(); }

/**
* Returns the number of buckets in the table.
*
* @return the bucket count
*/
size_type bucket_count() const { return buckets_.size(); }
[[nodiscard]] size_type bucket_count() const { return buckets_.size(); }

/**
* Returns whether the table is empty or not.
*
* @return true if the table is empty, false otherwise
*/
bool empty() const { return size() == 0; }
[[nodiscard]] bool empty() const { return size() == 0; }

/**
* Returns the number of elements in the table.
*
* @return number of elements in the table
*/
size_type size() const {
[[nodiscard]] size_type size() const {
if (all_locks_.size() == 0) {
return 0;
}
Expand All @@ -347,15 +348,15 @@ public:
*
* @return capacity of table
*/
size_type capacity() const { return bucket_count() * slot_per_bucket(); }
[[nodiscard]] size_type capacity() const { return bucket_count() * slot_per_bucket(); }

/**
* Returns the percentage the table is filled, that is, @ref size() &divide;
* @ref capacity().
*
* @return load factor of the table
*/
double load_factor() const {
[[nodiscard]] double load_factor() const {
return static_cast<double>(size()) / static_cast<double>(capacity());
}

Expand Down Expand Up @@ -622,7 +623,7 @@ public:
* Returns whether or not @p key is in the table. Equivalent to @ref
* find_fn with a functor that does nothing.
*/
template <typename K> bool contains(const K &key) const {
template <typename K> [[nodiscard]] bool contains(const K &key) const {
return find_fn(key, [](const mapped_type &) {});
}

Expand Down