Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions pp/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ http_archive(
"//third_party/patches/roaring:0001-disable-test-dependencies.patch",
"//third_party/patches/roaring:0002-svacer_fixes.patch",
],
patch_cmds = [
"cp cpp/* include/roaring"
],
sha256 = "a037e12a3f7c8c2abb3e81fc9669c23e274ffa2d8670d2034a2e05969e53689b",
strip_prefix = "CRoaring-1.3.0/",
url = "https://github.com/RoaringBitmap/CRoaring/archive/refs/tags/v1.3.0.zip",
Expand Down
22 changes: 20 additions & 2 deletions pp/primitives/label_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
namespace PromPP::Primitives {
template <class LabelType, template <class> class Container = BareBones::Vector>
class BasicLabelSet {
Container<LabelType> labels_;

public:
using label_type = LabelType;

Expand Down Expand Up @@ -68,6 +66,17 @@ class BasicLabelSet {
}
}

template <class LabelSet>
PROMPP_ALWAYS_INLINE void append_unsorted(const LabelSet& label_set) {
labels_.reserve(labels_.size() + label_set.size());

for (const auto& label : label_set) {
append(label.first, label.second);
}

sort();
}

template <class LabelSet>
PROMPP_ALWAYS_INLINE void add(const LabelSet& label_set) {
labels_.reserve(labels_.size() + label_set.size());
Expand Down Expand Up @@ -102,6 +111,8 @@ class BasicLabelSet {
[[nodiscard]] PROMPP_ALWAYS_INLINE const_iterator end() const noexcept { return labels_.end(); }
PROMPP_ALWAYS_INLINE iterator end() noexcept { return labels_.end(); }

[[nodiscard]] PROMPP_ALWAYS_INLINE const LabelType& operator[](uint32_t index) const noexcept { return labels_[index]; }

[[nodiscard]] PROMPP_ALWAYS_INLINE uint32_t allocated_memory() const noexcept { return BareBones::mem::allocated_memory(labels_); }

template <class T>
Expand Down Expand Up @@ -169,6 +180,13 @@ class BasicLabelSet {
};

[[nodiscard]] PROMPP_ALWAYS_INLINE Names names() const noexcept { return Names(*this); }

private:
Container<LabelType> labels_;

PROMPP_ALWAYS_INLINE void sort() noexcept {
std::ranges::sort(labels_, [](const auto& a, const auto& b) { return a.first < b.first; });
}
};

using LabelSet = BasicLabelSet<Label, std::vector>;
Expand Down
154 changes: 25 additions & 129 deletions pp/primitives/labels_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,11 @@
#include "primitives.h"

namespace PromPP::Primitives {
class LabelsBuilderStateMap {
PromPP::Primitives::LabelViewSet building_buf_view_;
PromPP::Primitives::LabelSet building_buf_;
phmap::flat_hash_map<Symbol, Symbol> buffer_;

template <class Labels>
void sort_labels(Labels& labels) {
std::ranges::sort(labels, [](const auto& a, const auto& b) {
if (a.first == b.first) {
return a.second < b.second;
}
return a.first < b.first;
});
}
class LabelsBuilder {
LabelViewSet building_buf_view_;
LabelSet building_buf_;
phmap::flat_hash_map<Symbol, Symbol> buffer_;

public:
// del add label name to remove from label set.
Expand All @@ -33,26 +24,26 @@ class LabelsBuilderStateMap {

// extract we extract(move) the lebel from the builder.
PROMPP_ALWAYS_INLINE Label extract(const std::string_view& lname) {
if (auto it = buffer_.find(lname); it != buffer_.end()) {
auto node = buffer_.extract(it);
if (const auto it = buffer_.find(lname); it != buffer_.end()) {
auto&& node = buffer_.extract(it);
return {std::move(const_cast<Symbol&>(node.key())), std::move(node.mapped())};
}

return {};
}

// get returns the value for the label with the given name. Returns an empty string if the label doesn't exist.
PROMPP_ALWAYS_INLINE std::string_view get(const std::string_view lname) {
if (auto it = buffer_.find(lname); it != buffer_.end()) {
return (*it).second;
PROMPP_ALWAYS_INLINE std::string_view get(const std::string_view& lname) {
if (const auto it = buffer_.find(lname); it != buffer_.end()) {
return it->second;
}

return "";
}

// contains check the given name if exist.
[[nodiscard]] PROMPP_ALWAYS_INLINE bool contains(const std::string_view lname) const noexcept {
if (auto it = buffer_.find(lname); it != buffer_.end()) {
[[nodiscard]] PROMPP_ALWAYS_INLINE bool contains(const std::string_view& lname) const noexcept {
if (const auto it = buffer_.find(lname); it != buffer_.end()) {
return true;
}

Expand All @@ -68,69 +59,42 @@ class LabelsBuilderStateMap {
}

if (auto it = buffer_.find(lname); it != buffer_.end()) {
(*it).second = lvalue;
it->second = lvalue;
return;
}

buffer_[lname] = lvalue;
}

// returns size of building labels.
PROMPP_ALWAYS_INLINE size_t size() { return buffer_.size(); }
[[nodiscard]] PROMPP_ALWAYS_INLINE size_t size() const { return buffer_.size(); }

// returns true if ls represents an empty set of labels.
PROMPP_ALWAYS_INLINE bool is_empty() { return buffer_.size() == 0; }
[[nodiscard]] PROMPP_ALWAYS_INLINE bool is_empty() const { return buffer_.empty(); }

// label_view_set - returns the label_view set from the builder. If no modifications were made, the original labels are returned.
PROMPP_ALWAYS_INLINE const LabelViewSet& label_view_set() {
building_buf_view_.clear();
for (const auto& it : buffer_) {
if (it.second == "") [[unlikely]] {
continue;
}

building_buf_view_.add(LabelView{it.first, it.second});
}

if (building_buf_view_.size() != 0) {
sort_labels(building_buf_view_);
}

building_buf_view_.append_unsorted(buffer_);
return building_buf_view_;
}

// label_set - returns the label set from the builder. If no modifications were made, the original labels are returned.
PROMPP_ALWAYS_INLINE const LabelSet& label_set() {
building_buf_.clear();

for (const auto& it : buffer_) {
if (it.second == "") [[unlikely]] {
continue;
}

building_buf_.add(Label{it.first, it.second});
}

if (building_buf_.size() != 0) {
sort_labels(building_buf_);
}

building_buf_.append_unsorted(buffer_);
return building_buf_;
}

// range - calls f on each label in the builder.
// TODO without copy buffer_, all changes in a another cycle.
// range - calls f on each label in the builder. Don't modify LabelsBuilderStateMap inside callback
template <class Callback>
PROMPP_ALWAYS_INLINE void range(Callback func) {
// take a copy of add and del, so they are unaffected by calls to set() or del().
phmap::flat_hash_map<Symbol, Symbol> cbuffer_ = buffer_;

for (const auto& it : cbuffer_) {
if (it.second == "") [[unlikely]] {
PROMPP_ALWAYS_INLINE void range(Callback func) const {
for (const auto& it : buffer_) {
if (it.second.empty()) [[unlikely]] {
continue;
}

if (bool ok = func(it.first, it.second); !ok) {
if (!func(it.first, it.second)) {
return;
}
}
Expand All @@ -145,83 +109,15 @@ class LabelsBuilderStateMap {

// reset - clears all current state for the builder.
template <class SomeLabelSet>
PROMPP_ALWAYS_INLINE void reset(SomeLabelSet& base) {
building_buf_view_.clear();
building_buf_.clear();
buffer_.clear();
PROMPP_ALWAYS_INLINE void reset(const SomeLabelSet& base) {
reset();

for (const auto& [lname, lvalue] : base) {
if (lvalue == "") {
continue;
if (!lvalue.empty()) [[likely]] {
buffer_[lname] = lvalue;
}

buffer_[lname] = lvalue;
}
}
};

// LabelsBuilder - builder for label set.
template <class BuilderState>
class LabelsBuilder {
BuilderState& state_;

public:
PROMPP_ALWAYS_INLINE explicit LabelsBuilder(BuilderState& state) : state_(state) {}

template <class SomeLabelSet>
PROMPP_ALWAYS_INLINE explicit LabelsBuilder(BuilderState& state, SomeLabelSet* ls) : state_(state) {
reset(ls);
}

// del - add label name to remove from label set.
template <class LNameType>
PROMPP_ALWAYS_INLINE void del(const LNameType& lname) {
state_.del(lname);
}

// extract we extract(move) the lebel from the builder.
PROMPP_ALWAYS_INLINE Label extract(const std::string_view& lname) { return state_.extract(lname); }

// get - returns the value for the label with the given name. Returns an empty string if the label doesn't exist.
PROMPP_ALWAYS_INLINE std::string_view get(const std::string_view lname) { return state_.get(lname); }

// contains check the given name if exist.
[[nodiscard]] PROMPP_ALWAYS_INLINE bool contains(const std::string_view lname) const noexcept { return state_.contains(lname); }

// returns size of building labels.
PROMPP_ALWAYS_INLINE size_t size() { return state_.size(); }

// returns true if ls represents an empty set of labels.
PROMPP_ALWAYS_INLINE bool is_empty() { return state_.is_empty(); }

// label_view_set - returns the label_view set from the builder. If no modifications were made, the original labels are returned.
PROMPP_ALWAYS_INLINE const PromPP::Primitives::LabelViewSet& label_view_set() { return state_.label_view_set(); }

// label_set - returns the label set from the builder. If no modifications were made, the original labels are returned.
PROMPP_ALWAYS_INLINE const PromPP::Primitives::LabelSet& label_set() { return state_.label_set(); }

// range - calls f on each label in the builder.
template <class Callback>
PROMPP_ALWAYS_INLINE void range(Callback func) {
state_.range(func);
}

// reset - clears all current state for the builder.
PROMPP_ALWAYS_INLINE void reset() { state_.reset(); }

// reset - clears all current state for the builder and init from LabelSet.
template <class SomeLabelSet>
PROMPP_ALWAYS_INLINE void reset(const SomeLabelSet& ls) {
state_.reset(ls);
}

// set - the name/value pair as a label. A value of "" means delete that label.
template <class LNameType, class LValueType>
PROMPP_ALWAYS_INLINE void set(const LNameType& lname, const LValueType& lvalue) {
state_.set(lname, lvalue);
}

PROMPP_ALWAYS_INLINE LabelsBuilder(LabelsBuilder&&) noexcept = default;
PROMPP_ALWAYS_INLINE ~LabelsBuilder() = default;
};
} // namespace PromPP::Primitives
Loading
Loading