Skip to content

Commit

Permalink
feat(buffer): make memory_buffer, span_buffer and static_buffer copy-…
Browse files Browse the repository at this point in the history
… and movable (#97)
  • Loading branch information
Viatorus authored Sep 20, 2024
1 parent a1a4584 commit 00a37cf
Show file tree
Hide file tree
Showing 5 changed files with 654 additions and 128 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,16 @@ jobs:
files: build/coverage.info

memcheck:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v3

- name: Install GCC
run: |
sudo apt update && sudo apt install -y gcc-11 g++-11
echo "CC=gcc-11" >> $GITHUB_ENV
echo "CXX=g++-11" >> $GITHUB_ENV
sudo apt update && sudo apt install -y gcc-14 g++-14
echo "CC=gcc-14" >> $GITHUB_ENV
echo "CXX=g++-14" >> $GITHUB_ENV
- name: Install valgrind
run: sudo apt update && sudo apt install -y valgrind
Expand All @@ -189,16 +189,16 @@ jobs:
fi
sanitize:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v3

- name: Install GCC
run: |
sudo apt update && sudo apt install -y gcc-11 g++-11
echo "CC=gcc-11" >> $GITHUB_ENV
echo "CXX=g++-11" >> $GITHUB_ENV
sudo apt update && sudo apt install -y gcc-14 g++-14
echo "CC=gcc-14" >> $GITHUB_ENV
echo "CXX=g++-14" >> $GITHUB_ENV
- name: Configure
run: cmake --preset=ci-sanitize
Expand Down
103 changes: 87 additions & 16 deletions include/emio/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <iterator>
#include <limits>
#include <span>
#include <utility>

#if __STDC_HOSTED__
# include <string>
Expand All @@ -31,10 +32,10 @@ inline constexpr size_t default_cache_size{128};
*/
class buffer {
public:
buffer(const buffer& other) = delete;
buffer(buffer&& other) = delete;
buffer& operator=(const buffer& other) = delete;
buffer& operator=(buffer&& other) = delete;
constexpr buffer(const buffer& other) = delete;
constexpr buffer(buffer&& other) = delete;
constexpr buffer& operator=(const buffer& other) = delete;
constexpr buffer& operator=(buffer&& other) = delete;
virtual constexpr ~buffer() noexcept = default;

/**
Expand Down Expand Up @@ -145,10 +146,40 @@ class memory_buffer final : public buffer {
static_cast<void>(request_write_area(0, std::max(vec_.capacity(), capacity)));
}

constexpr memory_buffer(const memory_buffer&) = default;
constexpr memory_buffer(memory_buffer&&) noexcept = default;
constexpr memory_buffer& operator=(const memory_buffer&) = default;
constexpr memory_buffer& operator=(memory_buffer&&) noexcept = default;
constexpr memory_buffer(const memory_buffer& other)
: buffer{}, used_{other.used_ + other.get_used_count()}, vec_{other.vec_} {
this->set_write_area({vec_.data() + used_, vec_.data() + vec_.capacity()});
}

constexpr memory_buffer(memory_buffer&& other) noexcept
: buffer{}, used_{other.used_ + other.get_used_count()}, vec_{std::move(other).vec_} {
this->set_write_area({vec_.data() + used_, vec_.data() + vec_.capacity()});
other.reset();
}

constexpr memory_buffer& operator=(const memory_buffer& other) {
if (&other == this) {
return *this;
}

used_ = other.used_ + other.get_used_count();
vec_ = other.vec_;
this->set_write_area({vec_.data() + used_, vec_.data() + vec_.capacity()});
return *this;
}

constexpr memory_buffer& operator=(memory_buffer&& other) noexcept {
if (&other == this) {
return *this;
}

used_ = other.used_ + other.get_used_count();
vec_ = std::move(other).vec_;
this->set_write_area({vec_.data() + used_, vec_.data() + vec_.capacity()});
other.reset();
return *this;
}

constexpr ~memory_buffer() override = default;

/**
Expand Down Expand Up @@ -219,10 +250,30 @@ class span_buffer : public buffer {
this->set_write_area(span_);
}

constexpr span_buffer(const span_buffer&) = delete;
constexpr span_buffer(span_buffer&&) noexcept = delete;
constexpr span_buffer& operator=(const span_buffer&) = delete;
constexpr span_buffer& operator=(span_buffer&&) noexcept = delete;
constexpr span_buffer(const span_buffer& other) : buffer{fixed_size::yes}, span_{other.span_} {
this->set_write_area(span_);
get_write_area_of(other.get_used_count()).value();
}

// NOLINTNEXTLINE(performance-move-constructor-init): optimized move not possible
constexpr span_buffer(span_buffer&& other) noexcept : span_buffer{std::as_const(other)} {}

constexpr span_buffer& operator=(const span_buffer& other) {
if (&other == this) {
return *this;
}

span_ = other.span_;
this->set_write_area(span_);
get_write_area_of(other.get_used_count()).value();
return *this;
}

constexpr span_buffer& operator=(span_buffer&& other) noexcept {
*this = std::as_const(other);
return *this;
}

constexpr ~span_buffer() override;

/**
Expand Down Expand Up @@ -277,10 +328,30 @@ class static_buffer final : private std::array<char, StorageSize>, public span_b
*/
constexpr static_buffer() noexcept : span_buffer{std::span{*this}} {}

constexpr static_buffer(const static_buffer&) = delete;
constexpr static_buffer(static_buffer&&) noexcept = delete;
constexpr static_buffer& operator=(const static_buffer&) = delete;
constexpr static_buffer& operator=(static_buffer&&) noexcept = delete;
constexpr static_buffer(const static_buffer& other) : static_buffer() {
const std::span<char> area = get_write_area_of(other.get_used_count()).value();
detail::copy_n(other.begin(), area.size(), area.data());
}

// NOLINTNEXTLINE(performance-move-constructor-init): optimized move not possible
constexpr static_buffer(static_buffer&& other) noexcept : static_buffer(std::as_const(other)) {}

constexpr static_buffer& operator=(const static_buffer& other) {
if (&other == this) {
return *this;
}

set_write_area(std::span{*this});
const std::span<char> area = get_write_area_of(other.get_used_count()).value();
detail::copy_n(other.begin(), area.size(), area.data());
return *this;
}

constexpr static_buffer& operator=(static_buffer&& other) noexcept {
*this = std::as_const(other);
return *this;
}

constexpr ~static_buffer() override = default;

// Note: We inherit from std::array to put the storage lifetime before span_buffer.
Expand Down
59 changes: 55 additions & 4 deletions include/emio/detail/ct_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,61 @@ class ct_vector {
}
}

ct_vector(const ct_vector&) = delete;
ct_vector(ct_vector&&) = delete;
ct_vector& operator=(const ct_vector&) = delete;
ct_vector& operator=(ct_vector&&) = delete;
constexpr ct_vector(const ct_vector& other) : ct_vector() {
reserve(other.size_);
copy_n(other.data_, other.size_, data_);
}

constexpr ct_vector(ct_vector&& other) noexcept : ct_vector() {
// Transfer ownership.
if (other.hold_external()) {
data_ = other.data_;
capacity_ = other.capacity_;
} else {
copy_n(other.data_, other.size_, data_);
}
size_ = other.size_;

// Reset other.
other.data_ = other.storage_.data();
other.size_ = 0;
other.capacity_ = StorageSize;
}

constexpr ct_vector& operator=(const ct_vector& other) {
if (&other == this) {
return *this;
}
reserve(other.size_);
copy_n(other.data_, other.size_, data_);
return *this;
}

constexpr ct_vector& operator=(ct_vector&& other) noexcept {
if (&other == this) {
return *this;
}

// Free this.
if (hold_external()) {
delete[] data_; // NOLINT(cppcoreguidelines-owning-memory)
}

// Transfer ownership.
if (other.hold_external()) {
data_ = other.data_;
capacity_ = other.capacity_;
} else {
copy_n(other.data_, other.size_, data_);
}
size_ = other.size_;

// Reset other.
other.data_ = other.storage_.data();
other.size_ = 0;
other.capacity_ = StorageSize;
return *this;
}

constexpr ~ct_vector() noexcept {
if (hold_external()) {
Expand Down
Loading

0 comments on commit 00a37cf

Please sign in to comment.