Skip to content
Draft
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
2 changes: 2 additions & 0 deletions CPPLINT.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ filter=-build/include_order,
filter=-build/include_subdir,
# Nice but reports a false positive in qsbr.hpp on std::max
filter=-build/include_what_you_use,
# False positives with [[likely]] and [[unlikely]]
filter=-readability/braces,
# clang-tidy owns NOLINT
filter=-readability/nolint,
filter=-runtime/references,
Expand Down
27 changes: 17 additions & 10 deletions art.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ detail::node_ptr *impl_helpers::add_or_choose_subtree(
const auto children_count = inode.get_children_count();

if constexpr (!std::is_same_v<INode, inode_256>) {
if (UNODB_DETAIL_UNLIKELY(children_count == INode::capacity)) {
if (children_count == INode::capacity) [[unlikely]] {
auto larger_node{INode::larger_derived_type::create(
db_instance, inode, std::move(aleaf), depth)};
*node_in_parent =
Expand Down Expand Up @@ -212,7 +212,7 @@ std::optional<detail::node_ptr *> impl_helpers::remove_or_choose_subtree(
const auto *const aleaf{child_ptr_val.template ptr<::leaf *>()};
if (!aleaf->matches(k)) return {};

if (UNODB_DETAIL_UNLIKELY(inode.is_min_size())) {
if (inode.is_min_size()) [[unlikely]] {
if constexpr (std::is_same_v<INode, inode_4>) {
auto current_node{
art_policy::make_db_inode_unique_ptr(&inode, db_instance)};
Expand Down Expand Up @@ -280,7 +280,8 @@ constexpr void db::account_shrinking_inode() noexcept {
#endif // UNODB_DETAIL_WITH_STATS

db::get_result db::get(key search_key) const noexcept {
if (UNODB_DETAIL_UNLIKELY(root == nullptr)) return {};
if (root == nullptr) [[unlikely]]
return {};

auto node{root};
const detail::art_key k{search_key};
Expand Down Expand Up @@ -315,7 +316,7 @@ UNODB_DETAIL_DISABLE_MSVC_WARNING(26430)
bool db::insert(key insert_key, value_view v) {
const auto k = detail::art_key{insert_key};

if (UNODB_DETAIL_UNLIKELY(root == nullptr)) {
if (root == nullptr) [[unlikely]] {
auto leaf = unodb::detail::art_policy::make_db_leaf_ptr(k, v, *this);
root = detail::node_ptr{leaf.release(), node_type::LEAF};
return true;
Expand All @@ -330,7 +331,8 @@ bool db::insert(key insert_key, value_view v) {
if (node_type == node_type::LEAF) {
auto *const leaf{node->ptr<::leaf *>()};
const auto existing_key{leaf->get_key()};
if (UNODB_DETAIL_UNLIKELY(k == existing_key)) return false;
if (k == existing_key) [[unlikely]]
return false;

auto new_leaf = unodb::detail::art_policy::make_db_leaf_ptr(k, v, *this);
auto new_node{detail::inode_4::create(*this, existing_key, remaining_key,
Expand Down Expand Up @@ -381,7 +383,8 @@ UNODB_DETAIL_RESTORE_MSVC_WARNINGS()
bool db::remove(key remove_key) {
const auto k = detail::art_key{remove_key};

if (UNODB_DETAIL_UNLIKELY(root == nullptr)) return false;
if (root == nullptr) [[unlikely]]
return false;

if (root.type() == node_type::LEAF) {
auto *const root_leaf{root.ptr<leaf *>()};
Expand Down Expand Up @@ -416,7 +419,8 @@ bool db::remove(key remove_key) {
const auto remove_result{
inode->remove_or_choose_subtree<std::optional<detail::node_ptr *>>(
node_type, remaining_key[0], k, *this, node)};
if (UNODB_DETAIL_UNLIKELY(!remove_result)) return false;
if (!remove_result) [[unlikely]]
return false;

auto *const child_ptr{*remove_result};
if (child_ptr == nullptr) return true;
Expand Down Expand Up @@ -501,7 +505,8 @@ void db::iterator::dump() const { dump(std::cerr); }
// If the tree is empty, then the result is the same as end().
db::iterator &db::iterator::first() {
invalidate(); // clear the stack
if (UNODB_DETAIL_UNLIKELY(db_.root == nullptr)) return *this; // empty tree.
if (db_.root == nullptr) [[unlikely]]
return *this; // empty tree.
auto node{db_.root};
return left_most_traversal(node);
}
Expand All @@ -511,7 +516,8 @@ db::iterator &db::iterator::first() {
// If the tree is empty, then the result is the same as end().
db::iterator &db::iterator::last() {
invalidate(); // clear the stack
if (UNODB_DETAIL_UNLIKELY(db_.root == nullptr)) return *this; // empty tree.
if (db_.root == nullptr) [[unlikely]]
return *this; // empty tree.
auto node{db_.root};
return right_most_traversal(node);
}
Expand Down Expand Up @@ -625,7 +631,8 @@ db::iterator &db::iterator::seek(detail::art_key search_key, bool &match,
bool fwd) {
invalidate(); // invalidate the iterator (clear the stack).
match = false; // unless we wind up with an exact match.
if (UNODB_DETAIL_UNLIKELY(db_.root == nullptr)) return *this; // aka end()
if (db_.root == nullptr) [[unlikely]]
return *this; // aka end()

auto node{db_.root};
const detail::art_key k = search_key;
Expand Down
18 changes: 12 additions & 6 deletions art.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,15 +573,17 @@ inline void db::scan(FN fn, bool fwd) {
it.first();
visitor<db::iterator> v{it};
while (it.valid()) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.next();
}
} else {
iterator it(*this);
it.last();
visitor<db::iterator> v{it};
while (it.valid()) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.prior();
}
}
Expand All @@ -596,15 +598,17 @@ inline void db::scan_from(key from_key, FN fn, bool fwd) {
it.seek(from_key_, match, true /*fwd*/);
visitor<db::iterator> v{it};
while (it.valid()) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.next();
}
} else {
iterator it(*this);
it.seek(from_key_, match, false /*fwd*/);
visitor<db::iterator> v{it};
while (it.valid()) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.prior();
}
}
Expand All @@ -629,7 +633,8 @@ inline void db::scan_range(key from_key, const key to_key, FN fn) {
}
visitor<db::iterator> v{it};
while (it.valid() && it.cmp(to_key_) < 0) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.next();
if constexpr (debug) {
std::cerr << "scan_range:: next()\n";
Expand All @@ -646,7 +651,8 @@ inline void db::scan_range(key from_key, const key to_key, FN fn) {
}
visitor<db::iterator> v{it};
while (it.valid() && it.cmp(to_key_) > 0) {
if (UNODB_DETAIL_UNLIKELY(fn(v))) break;
if (fn(v)) [[unlikely]]
break;
it.prior();
if constexpr (debug) {
std::cerr << "scan_range:: prior()\n";
Expand Down
2 changes: 1 addition & 1 deletion art_internal_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ template <class Header, class Db>
Db &db UNODB_DETAIL_LIFETIMEBOUND) {
using leaf_type = basic_leaf<Header>;

if (UNODB_DETAIL_UNLIKELY(v.size() > leaf_type::max_value_size)) {
if (v.size() > leaf_type::max_value_size) [[unlikely]] {
throw std::length_error("Value length must fit in std::uint32_t");
}

Expand Down
9 changes: 8 additions & 1 deletion global.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019-2022 Laurynas Biveinis
// Copyright 2019-2025 Laurynas Biveinis
#ifndef UNODB_DETAIL_GLOBAL_HPP
#define UNODB_DETAIL_GLOBAL_HPP

Expand Down Expand Up @@ -102,8 +102,11 @@

#endif

// Use only in the contexts where C++20 [[likely]] and [[unlikely]] are illegal,
// i.e. in subexpressions, return statements, ternary operator.
#define UNODB_DETAIL_LIKELY(x) __builtin_expect(x, 1)
#define UNODB_DETAIL_UNLIKELY(x) __builtin_expect(x, 0)

#define UNODB_DETAIL_UNUSED [[gnu::unused]]
#define UNODB_DETAIL_FORCE_INLINE __attribute__((always_inline))
#define UNODB_DETAIL_NOINLINE __attribute__((noinline))
Expand All @@ -113,8 +116,12 @@
#else // #ifndef UNODB_DETAIL_MSVC

#define UNODB_DETAIL_BUILTIN_ASSUME(x) __assume(x)

// Use only in the contexts where C++20 [[likely]] and [[unlikely]] are illegal,
// i.e. in subexpressions, return statements, ternary operator.
#define UNODB_DETAIL_LIKELY(x) (!!(x))
#define UNODB_DETAIL_UNLIKELY(x) (!!(x))

#define UNODB_DETAIL_UNUSED [[maybe_unused]]
#define UNODB_DETAIL_FORCE_INLINE __forceinline
#define UNODB_DETAIL_NOINLINE __declspec(noinline)
Expand Down
7 changes: 4 additions & 3 deletions heap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ template <typename T>

#ifndef _MSC_VER
const auto err = posix_memalign(&result, alignment, size);
if (UNODB_DETAIL_UNLIKELY(err != 0)) result = nullptr;
if (err != 0) [[unlikely]]
result = nullptr; // LCOV_EXCL_LINE
#else
result = _aligned_malloc(size, alignment);
#ifndef NDEBUG
Expand All @@ -57,8 +58,8 @@ template <typename T>
// NOLINTNEXTLINE(readability-simplify-boolean-expr)
UNODB_DETAIL_ASSERT(result != nullptr || err == ENOMEM);

if (UNODB_DETAIL_UNLIKELY(result == nullptr)) {
throw std::bad_alloc{};
if (result == nullptr) [[unlikely]] {
throw std::bad_alloc{}; // LCOV_EXCL_LINE
}

return result;
Expand Down
Loading