309 lines
9.5 KiB
C++
309 lines
9.5 KiB
C++
// Copyright 2023 Memgraph Ltd.
|
|
//
|
|
// Use of this software is governed by the Business Source License
|
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
|
// License, and you may not use this file except in compliance with the Business Source License.
|
|
//
|
|
// As of the Change Date specified in that file, in accordance with
|
|
// the Business Source License, use of this software will be governed
|
|
// by the Apache License, Version 2.0, included in the file
|
|
// licenses/APL.txt.
|
|
|
|
#pragma once
|
|
|
|
#include <iterator>
|
|
|
|
#include <gflags/gflags.h>
|
|
|
|
#include "query/v2/bindings/frame.hpp"
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
|
DECLARE_uint64(default_multi_frame_size);
|
|
|
|
namespace memgraph::query::v2 {
|
|
|
|
class ValidFramesConsumer;
|
|
class ValidFramesModifier;
|
|
class ValidFramesReader;
|
|
class InvalidFramesPopulator;
|
|
|
|
class MultiFrame {
|
|
public:
|
|
friend class ValidFramesConsumer;
|
|
friend class ValidFramesModifier;
|
|
friend class ValidFramesReader;
|
|
friend class InvalidFramesPopulator;
|
|
|
|
MultiFrame(size_t size_of_frame, size_t number_of_frames, utils::MemoryResource *execution_memory);
|
|
~MultiFrame() = default;
|
|
|
|
// Assigning and moving the MultiFrame is not allowed if any accessor from the above ones are alive.
|
|
MultiFrame(const MultiFrame &other);
|
|
MultiFrame(MultiFrame &&other) noexcept;
|
|
MultiFrame &operator=(const MultiFrame &other) = delete;
|
|
MultiFrame &operator=(MultiFrame &&other) noexcept = delete;
|
|
|
|
/*
|
|
* Returns a object on which one can iterate in a for-loop. By doing so, you will only get Frames that are in a valid
|
|
* state in the MultiFrame.
|
|
* Iteration goes in a deterministic order.
|
|
* One can't modify the validity of the Frame nor its content with this implementation.
|
|
*/
|
|
ValidFramesReader GetValidFramesReader();
|
|
|
|
/*
|
|
* Returns a object on which one can iterate in a for-loop. By doing so, you will only get Frames that are in a valid
|
|
* state in the MultiFrame.
|
|
* Iteration goes in a deterministic order.
|
|
* One can't modify the validity of the Frame with this implementation. One can modify its content.
|
|
*/
|
|
ValidFramesModifier GetValidFramesModifier();
|
|
|
|
/*
|
|
* Returns a object on which one can iterate in a for-loop. By doing so, you will only get Frames that are in a valid
|
|
* state in the MultiFrame.
|
|
* Iteration goes in a deterministic order.
|
|
* One can modify the validity of the Frame with this implementation.
|
|
* If you do not plan to modify the validity of the Frames, use GetValidFramesReader/GetValidFramesModifer instead as
|
|
* this is faster.
|
|
*/
|
|
ValidFramesConsumer GetValidFramesConsumer();
|
|
|
|
/*
|
|
* Returns a object on which one can iterate in a for-loop. By doing so, you will only get Frames that are in an
|
|
* invalid state in the MultiFrame. Iteration goes in a deterministic order. One can modify the validity of
|
|
* the Frame with this implementation.
|
|
*/
|
|
InvalidFramesPopulator GetInvalidFramesPopulator();
|
|
|
|
/**
|
|
* Return the first Frame of the MultiFrame. This is only meant to be used in very specific cases. Please consider
|
|
* using the iterators instead.
|
|
* The Frame can be valid or invalid.
|
|
*/
|
|
FrameWithValidity &GetFirstFrame();
|
|
|
|
void MakeAllFramesInvalid() noexcept;
|
|
|
|
bool HasValidFrame() const noexcept;
|
|
bool HasInvalidFrame() const noexcept;
|
|
|
|
inline utils::MemoryResource *GetMemoryResource() { return frames_[0].GetMemoryResource(); }
|
|
|
|
private:
|
|
void DefragmentValidFrames() noexcept;
|
|
|
|
utils::pmr::vector<FrameWithValidity> frames_;
|
|
};
|
|
|
|
class ValidFramesReader {
|
|
public:
|
|
explicit ValidFramesReader(MultiFrame &multiframe);
|
|
|
|
~ValidFramesReader() = default;
|
|
ValidFramesReader(const ValidFramesReader &other) = delete;
|
|
ValidFramesReader(ValidFramesReader &&other) noexcept = default;
|
|
ValidFramesReader &operator=(const ValidFramesReader &other) = delete;
|
|
ValidFramesReader &operator=(ValidFramesReader &&other) noexcept = default;
|
|
|
|
struct Iterator {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = const Frame;
|
|
using pointer = value_type *;
|
|
using reference = const Frame &;
|
|
|
|
Iterator() = default;
|
|
explicit Iterator(FrameWithValidity *ptr) : ptr_(ptr) {}
|
|
|
|
reference operator*() const { return *ptr_; }
|
|
pointer operator->() { return ptr_; }
|
|
|
|
Iterator &operator++() {
|
|
ptr_++;
|
|
return *this;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
|
Iterator operator++(int) {
|
|
auto old = *this;
|
|
ptr_++;
|
|
return old;
|
|
}
|
|
|
|
friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ == rhs.ptr_; };
|
|
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ != rhs.ptr_; };
|
|
|
|
private:
|
|
FrameWithValidity *ptr_{nullptr};
|
|
};
|
|
|
|
Iterator begin();
|
|
Iterator end();
|
|
|
|
private:
|
|
FrameWithValidity *after_last_valid_frame_;
|
|
MultiFrame *multiframe_;
|
|
};
|
|
|
|
class ValidFramesModifier {
|
|
public:
|
|
explicit ValidFramesModifier(MultiFrame &multiframe);
|
|
|
|
~ValidFramesModifier() = default;
|
|
ValidFramesModifier(const ValidFramesModifier &other) = delete;
|
|
ValidFramesModifier(ValidFramesModifier &&other) noexcept = default;
|
|
ValidFramesModifier &operator=(const ValidFramesModifier &other) = delete;
|
|
ValidFramesModifier &operator=(ValidFramesModifier &&other) noexcept = default;
|
|
|
|
struct Iterator {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = Frame;
|
|
using pointer = value_type *;
|
|
using reference = Frame &;
|
|
|
|
Iterator() = default;
|
|
Iterator(FrameWithValidity *ptr, ValidFramesModifier &iterator_wrapper)
|
|
: ptr_(ptr), iterator_wrapper_(&iterator_wrapper) {}
|
|
|
|
reference operator*() const { return *ptr_; }
|
|
pointer operator->() { return ptr_; }
|
|
|
|
// Prefix increment
|
|
Iterator &operator++() {
|
|
do {
|
|
ptr_++;
|
|
} while (*this != iterator_wrapper_->end() && !ptr_->IsValid());
|
|
|
|
return *this;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
|
Iterator operator++(int) {
|
|
auto old = *this;
|
|
++*this;
|
|
return old;
|
|
}
|
|
|
|
friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ == rhs.ptr_; };
|
|
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ != rhs.ptr_; };
|
|
|
|
private:
|
|
FrameWithValidity *ptr_{nullptr};
|
|
ValidFramesModifier *iterator_wrapper_{nullptr};
|
|
};
|
|
|
|
Iterator begin();
|
|
Iterator end();
|
|
|
|
private:
|
|
MultiFrame *multiframe_;
|
|
};
|
|
|
|
class ValidFramesConsumer {
|
|
public:
|
|
explicit ValidFramesConsumer(MultiFrame &multiframe);
|
|
|
|
~ValidFramesConsumer() noexcept;
|
|
ValidFramesConsumer(const ValidFramesConsumer &other) = delete;
|
|
ValidFramesConsumer(ValidFramesConsumer &&other) noexcept = default;
|
|
ValidFramesConsumer &operator=(const ValidFramesConsumer &other) = delete;
|
|
ValidFramesConsumer &operator=(ValidFramesConsumer &&other) noexcept = default;
|
|
|
|
struct Iterator {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = FrameWithValidity;
|
|
using pointer = value_type *;
|
|
using reference = FrameWithValidity &;
|
|
|
|
Iterator() = default;
|
|
Iterator(FrameWithValidity *ptr, ValidFramesConsumer &iterator_wrapper)
|
|
: ptr_(ptr), iterator_wrapper_(&iterator_wrapper) {}
|
|
|
|
reference operator*() const { return *ptr_; }
|
|
pointer operator->() { return ptr_; }
|
|
|
|
Iterator &operator++() {
|
|
do {
|
|
ptr_++;
|
|
} while (*this != iterator_wrapper_->end() && !ptr_->IsValid());
|
|
|
|
return *this;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
|
Iterator operator++(int) {
|
|
auto old = *this;
|
|
++*this;
|
|
return old;
|
|
}
|
|
|
|
friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ == rhs.ptr_; };
|
|
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ != rhs.ptr_; };
|
|
|
|
private:
|
|
FrameWithValidity *ptr_{nullptr};
|
|
ValidFramesConsumer *iterator_wrapper_{nullptr};
|
|
};
|
|
|
|
Iterator begin();
|
|
Iterator end();
|
|
|
|
private:
|
|
MultiFrame *multiframe_;
|
|
};
|
|
|
|
class InvalidFramesPopulator {
|
|
public:
|
|
explicit InvalidFramesPopulator(MultiFrame &multiframe);
|
|
~InvalidFramesPopulator() = default;
|
|
|
|
InvalidFramesPopulator(const InvalidFramesPopulator &other) = delete;
|
|
InvalidFramesPopulator(InvalidFramesPopulator &&other) noexcept = default;
|
|
InvalidFramesPopulator &operator=(const InvalidFramesPopulator &other) = delete;
|
|
InvalidFramesPopulator &operator=(InvalidFramesPopulator &&other) noexcept = default;
|
|
|
|
struct Iterator {
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = FrameWithValidity;
|
|
using pointer = value_type *;
|
|
using reference = FrameWithValidity &;
|
|
|
|
Iterator() = default;
|
|
explicit Iterator(FrameWithValidity *ptr) : ptr_(ptr) {}
|
|
|
|
reference operator*() const { return *ptr_; }
|
|
pointer operator->() { return ptr_; }
|
|
|
|
Iterator &operator++() {
|
|
ptr_->MakeValid();
|
|
ptr_++;
|
|
return *this;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
|
Iterator operator++(int) {
|
|
auto old = *this;
|
|
++ptr_;
|
|
return old;
|
|
}
|
|
|
|
friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ == rhs.ptr_; };
|
|
friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return lhs.ptr_ != rhs.ptr_; };
|
|
|
|
private:
|
|
FrameWithValidity *ptr_{nullptr};
|
|
};
|
|
|
|
Iterator begin();
|
|
Iterator end();
|
|
|
|
private:
|
|
MultiFrame *multiframe_;
|
|
};
|
|
|
|
} // namespace memgraph::query::v2
|