Files
allwpilib/wpiutil/src/main/native/include/wpi/uv/Buffer.h
Peter Johnson b2c3b2dd8e Use std::string_view and fmtlib across all libraries (#3402)
- Twine, StringRef, Format, and NativeFormatting have been removed
- Logging now uses fmtlib style formatting
- Nearly all uses of wpi::outs/errs have been replaced with fmt::print() or
std::puts()/std::fputs() (for unformatted strings).
- A wpi/fmt/raw_ostream.h header has been added to enable
fmt::print() with wpi::raw_ostream
2021-06-06 16:13:58 -07:00

164 lines
3.8 KiB
C++

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#ifndef WPIUTIL_WPI_UV_BUFFER_H_
#define WPIUTIL_WPI_UV_BUFFER_H_
#include <uv.h>
#include <cstring>
#include <initializer_list>
#include <string_view>
#include <utility>
#include "wpi/ArrayRef.h"
#include "wpi/SmallVector.h"
namespace wpi::uv {
/**
* Data buffer. Convenience wrapper around uv_buf_t.
*/
class Buffer : public uv_buf_t {
public:
Buffer() {
base = nullptr;
len = 0;
}
/*implicit*/ Buffer(const uv_buf_t& oth) { // NOLINT
base = oth.base;
len = oth.len;
}
/*implicit*/ Buffer(std::string_view str) // NOLINT
: Buffer{str.data(), str.size()} {}
/*implicit*/ Buffer(ArrayRef<uint8_t> arr) // NOLINT
: Buffer{reinterpret_cast<const char*>(arr.data()), arr.size()} {}
Buffer(char* base_, size_t len_) {
base = base_;
len = static_cast<decltype(len)>(len_);
}
Buffer(const char* base_, size_t len_) {
base = const_cast<char*>(base_);
len = static_cast<decltype(len)>(len_);
}
ArrayRef<char> data() const { return ArrayRef<char>{base, len}; }
MutableArrayRef<char> data() { return MutableArrayRef<char>{base, len}; }
operator ArrayRef<char>() const { return data(); } // NOLINT
operator MutableArrayRef<char>() { return data(); } // NOLINT
static Buffer Allocate(size_t size) { return Buffer{new char[size], size}; }
static Buffer Dup(std::string_view in) {
Buffer buf = Allocate(in.size());
std::memcpy(buf.base, in.data(), in.size());
return buf;
}
static Buffer Dup(ArrayRef<uint8_t> in) {
Buffer buf = Allocate(in.size());
std::memcpy(buf.base, in.begin(), in.size());
return buf;
}
Buffer Dup() const {
Buffer buf = Allocate(len);
std::memcpy(buf.base, base, len);
return buf;
}
void Deallocate() {
delete[] base;
base = nullptr;
len = 0;
}
Buffer Move() {
Buffer buf = *this;
base = nullptr;
len = 0;
return buf;
}
friend void swap(Buffer& a, Buffer& b) {
using std::swap;
swap(a.base, b.base);
swap(a.len, b.len);
}
};
/**
* A simple pool allocator for Buffers.
* Buffers are allocated individually but are reused rather than returned
* to the heap.
* @tparam DEPTH depth of pool
*/
template <size_t DEPTH = 4>
class SimpleBufferPool {
public:
/**
* Constructor.
* @param size Size of each buffer to allocate.
*/
explicit SimpleBufferPool(size_t size = 4096) : m_size{size} {}
~SimpleBufferPool() { Clear(); }
SimpleBufferPool(const SimpleBufferPool& other) = delete;
SimpleBufferPool& operator=(const SimpleBufferPool& other) = delete;
/**
* Allocate a buffer.
*/
Buffer Allocate() {
if (m_pool.empty()) {
return Buffer::Allocate(m_size);
}
auto buf = m_pool.back();
m_pool.pop_back();
buf.len = m_size;
return buf;
}
/**
* Allocate a buffer.
*/
Buffer operator()() { return Allocate(); }
/**
* Release allocated buffers back into the pool.
* This is NOT safe to use with arbitrary buffers unless they were
* allocated with the same size as the buffer pool allocation size.
*/
void Release(MutableArrayRef<Buffer> bufs) {
for (auto& buf : bufs) {
m_pool.emplace_back(buf.Move());
}
}
/**
* Clear the pool, releasing all buffers.
*/
void Clear() {
for (auto& buf : m_pool) {
buf.Deallocate();
}
m_pool.clear();
}
/**
* Get number of buffers left in the pool before a new buffer will be
* allocated from the heap.
*/
size_t Remaining() const { return m_pool.size(); }
private:
SmallVector<Buffer, DEPTH> m_pool;
size_t m_size; // NOLINT
};
} // namespace wpi::uv
#endif // WPIUTIL_WPI_UV_BUFFER_H_