util/{HugeAllocator,SparseBuffer}: use std::span
This commit is contained in:
parent
84e5da4bf0
commit
b37c031fd1
|
@ -20,6 +20,7 @@
|
|||
#ifndef MPD_MUSIC_BUFFER_HXX
|
||||
#define MPD_MUSIC_BUFFER_HXX
|
||||
|
||||
#include "MusicChunk.hxx"
|
||||
#include "MusicChunkPtr.hxx"
|
||||
#include "util/SliceBuffer.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
|
|
|
@ -84,8 +84,8 @@ BufferingInputStream::Read(std::unique_lock<Mutex> &lock, size_t offset,
|
|||
auto r = buffer.Read(offset);
|
||||
if (r.HasData()) {
|
||||
/* yay, we have some data */
|
||||
size_t nbytes = std::min(s, r.defined_buffer.size);
|
||||
memcpy(ptr, r.defined_buffer.data, nbytes);
|
||||
size_t nbytes = std::min(s, r.defined_buffer.size());
|
||||
memcpy(ptr, r.defined_buffer.data(), nbytes);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,9 @@ BufferingInputStream::FindFirstHole() const noexcept
|
|||
/* a hole at the beginning */
|
||||
return 0;
|
||||
|
||||
if (r.defined_buffer.size < size())
|
||||
if (r.defined_buffer.size() < size())
|
||||
/* a hole in the middle */
|
||||
return r.defined_buffer.size;
|
||||
return r.defined_buffer.size();
|
||||
|
||||
/* the file has been read completely */
|
||||
return INVALID_OFFSET;
|
||||
|
@ -163,10 +163,10 @@ BufferingInputStream::RunThreadLocked(std::unique_lock<Mutex> &lock)
|
|||
hard disk, instead of returning when "some"
|
||||
data has been read */
|
||||
constexpr size_t MAX_READ = 64 * 1024;
|
||||
if (w.size > MAX_READ)
|
||||
w.size = MAX_READ;
|
||||
|
||||
size_t nbytes = input->Read(lock, w.data, w.size);
|
||||
size_t nbytes = input->Read(lock, w.data(),
|
||||
std::min(w.size(),
|
||||
MAX_READ));
|
||||
buffer.Commit(read_offset, read_offset + nbytes);
|
||||
|
||||
client_cond.notify_all();
|
||||
|
|
|
@ -56,7 +56,7 @@ AlignToPageSize(size_t size) noexcept
|
|||
return (size + ps - 1) / ps * ps;
|
||||
}
|
||||
|
||||
WritableBuffer<void>
|
||||
std::span<std::byte>
|
||||
HugeAllocate(size_t size)
|
||||
{
|
||||
size = AlignToPageSize(size);
|
||||
|
@ -74,7 +74,7 @@ HugeAllocate(size_t size)
|
|||
madvise(p, size, MADV_HUGEPAGE);
|
||||
#endif
|
||||
|
||||
return {p, size};
|
||||
return {(std::byte *)p, size};
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -108,7 +108,7 @@ HugeDiscard(void *p, size_t size) noexcept
|
|||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
WritableBuffer<void>
|
||||
std::span<std::byte>
|
||||
HugeAllocate(size_t size)
|
||||
{
|
||||
// TODO: use MEM_LARGE_PAGES
|
||||
|
@ -119,7 +119,7 @@ HugeAllocate(size_t size)
|
|||
throw std::bad_alloc();
|
||||
|
||||
// TODO: round size up to the page size
|
||||
return {p, size};
|
||||
return {(std::byte *)p, size};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HUGE_ALLOCATOR_HXX
|
||||
#define HUGE_ALLOCATOR_HXX
|
||||
#pragma once
|
||||
|
||||
#include "WritableBuffer.hxx"
|
||||
#include "SpanCast.hxx"
|
||||
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -48,7 +48,7 @@
|
|||
* (to the next page size), so callers can take advantage of this
|
||||
* allocation overhead
|
||||
*/
|
||||
WritableBuffer<void>
|
||||
std::span<std::byte>
|
||||
HugeAllocate(size_t size);
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,7 @@ HugeDiscard(void *p, size_t size) noexcept;
|
|||
#elif defined(_WIN32)
|
||||
#include <memoryapi.h>
|
||||
|
||||
WritableBuffer<void>
|
||||
std::span<std::byte>
|
||||
HugeAllocate(size_t size);
|
||||
|
||||
static inline void
|
||||
|
@ -118,16 +118,16 @@ HugeDiscard(void *p, size_t size) noexcept
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
static inline WritableBuffer<void>
|
||||
static inline std::span<std::byte>
|
||||
HugeAllocate(size_t size)
|
||||
{
|
||||
return {new uint8_t[size], size};
|
||||
return {new std::byte[size], size};
|
||||
}
|
||||
|
||||
static inline void
|
||||
HugeFree(void *_p, size_t) noexcept
|
||||
{
|
||||
auto *p = (uint8_t *)_p;
|
||||
auto *p = (std::byte *)_p;
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ HugeDiscard(void *, size_t) noexcept
|
|||
*/
|
||||
template<typename T>
|
||||
class HugeArray {
|
||||
typedef WritableBuffer<T> Buffer;
|
||||
using Buffer = std::span<T>;
|
||||
Buffer buffer{nullptr};
|
||||
|
||||
public:
|
||||
|
@ -162,20 +162,19 @@ public:
|
|||
typedef typename Buffer::reference reference;
|
||||
typedef typename Buffer::const_reference const_reference;
|
||||
typedef typename Buffer::iterator iterator;
|
||||
typedef typename Buffer::const_iterator const_iterator;
|
||||
|
||||
constexpr HugeArray() = default;
|
||||
|
||||
explicit HugeArray(size_type _size)
|
||||
:buffer(Buffer::FromVoidFloor(HugeAllocate(sizeof(value_type) * _size))) {}
|
||||
:buffer(FromBytesFloor<value_type>(HugeAllocate(sizeof(value_type) * _size))) {}
|
||||
|
||||
constexpr HugeArray(HugeArray &&other) noexcept
|
||||
:buffer(std::exchange(other.buffer, nullptr)) {}
|
||||
|
||||
~HugeArray() noexcept {
|
||||
if (buffer != nullptr) {
|
||||
auto v = buffer.ToVoid();
|
||||
HugeFree(v.data, v.size);
|
||||
if (!buffer.empty()) {
|
||||
auto v = std::as_writable_bytes(buffer);
|
||||
HugeFree(v.data(), v.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,18 +185,18 @@ public:
|
|||
}
|
||||
|
||||
void SetName(const char *name) noexcept {
|
||||
const auto v = buffer.ToVoid();
|
||||
HugeSetName(v.data, v.size, name);
|
||||
const auto v = std::as_writable_bytes(buffer);
|
||||
HugeSetName(v.data(), v.size(), name);
|
||||
}
|
||||
|
||||
void ForkCow(bool enable) noexcept {
|
||||
auto v = buffer.ToVoid();
|
||||
HugeForkCow(v.data, v.size, enable);
|
||||
const auto v = std::as_writable_bytes(buffer);
|
||||
HugeForkCow(v.data(), v.size(), enable);
|
||||
}
|
||||
|
||||
void Discard() noexcept {
|
||||
auto v = buffer.ToVoid();
|
||||
HugeDiscard(v.data, v.size);
|
||||
const auto v = std::as_writable_bytes(buffer);
|
||||
HugeDiscard(v.data(), v.size());
|
||||
}
|
||||
|
||||
constexpr bool operator==(std::nullptr_t) const noexcept {
|
||||
|
@ -212,7 +211,7 @@ public:
|
|||
* Returns the number of allocated elements.
|
||||
*/
|
||||
constexpr size_type size() const noexcept {
|
||||
return buffer.size;
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
reference front() noexcept {
|
||||
|
@ -249,17 +248,15 @@ public:
|
|||
return buffer.begin();
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() const noexcept {
|
||||
return buffer.cbegin();
|
||||
constexpr auto begin() const noexcept {
|
||||
return buffer.begin();
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
return buffer.end();
|
||||
}
|
||||
|
||||
constexpr const_iterator end() const noexcept {
|
||||
return buffer.cend();
|
||||
constexpr auto end() const noexcept {
|
||||
return buffer.end();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2022 Max Kellermann <max.kellermann@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
|
||||
/**
|
||||
* Cast a std::span<std::byte> to a std::span<T>, rounding down to the
|
||||
* next multiple of T's size.
|
||||
*/
|
||||
template<typename T>
|
||||
constexpr std::span<T>
|
||||
FromBytesFloor(std::span<std::byte> other) noexcept
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "Empty base type");
|
||||
|
||||
return {
|
||||
reinterpret_cast<T *>(other.data()),
|
||||
other.size() / sizeof(T),
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2018 Max Kellermann <max.kellermann@gmail.com>
|
||||
* Copyright 2013-2022 Max Kellermann <max.kellermann@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -27,12 +27,9 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SPARSE_BUFFER_HXX
|
||||
#define SPARSE_BUFFER_HXX
|
||||
#pragma once
|
||||
|
||||
#include "HugeAllocator.hxx"
|
||||
#include "ConstBuffer.hxx"
|
||||
#include "WritableBuffer.hxx"
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
@ -118,7 +115,7 @@ public:
|
|||
|
||||
struct ReadResult {
|
||||
size_type undefined_size;
|
||||
ConstBuffer<T> defined_buffer;
|
||||
std::span<const T> defined_buffer;
|
||||
|
||||
constexpr bool HasData() const noexcept {
|
||||
return undefined_size == 0 &&
|
||||
|
@ -131,7 +128,7 @@ public:
|
|||
return {c.undefined_size, {&buffer.front() + offset + c.undefined_size, c.defined_size}};
|
||||
}
|
||||
|
||||
WritableBuffer<T> Write(size_type offset) noexcept {
|
||||
std::span<T> Write(size_type offset) noexcept {
|
||||
auto c = map.Check(offset);
|
||||
return {&buffer.front() + offset, c.undefined_size};
|
||||
}
|
||||
|
@ -140,5 +137,3 @@ public:
|
|||
map.Commit(start_offset, end_offset);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue