diff --git a/src/MusicBuffer.hxx b/src/MusicBuffer.hxx index 0d1aedd2b..f2a8d4470 100644 --- a/src/MusicBuffer.hxx +++ b/src/MusicBuffer.hxx @@ -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" diff --git a/src/input/BufferingInputStream.cxx b/src/input/BufferingInputStream.cxx index e1cd0b304..172ee2b65 100644 --- a/src/input/BufferingInputStream.cxx +++ b/src/input/BufferingInputStream.cxx @@ -84,8 +84,8 @@ BufferingInputStream::Read(std::unique_lock &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 &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(); diff --git a/src/util/HugeAllocator.cxx b/src/util/HugeAllocator.cxx index 48cdba720..7dd0b61b8 100644 --- a/src/util/HugeAllocator.cxx +++ b/src/util/HugeAllocator.cxx @@ -56,7 +56,7 @@ AlignToPageSize(size_t size) noexcept return (size + ps - 1) / ps * ps; } -WritableBuffer +std::span 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 +std::span 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 diff --git a/src/util/HugeAllocator.hxx b/src/util/HugeAllocator.hxx index d87517e92..1169a176b 100644 --- a/src/util/HugeAllocator.hxx +++ b/src/util/HugeAllocator.hxx @@ -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 +#include #include #ifdef __linux__ @@ -48,7 +48,7 @@ * (to the next page size), so callers can take advantage of this * allocation overhead */ -WritableBuffer +std::span HugeAllocate(size_t size); /** @@ -87,7 +87,7 @@ HugeDiscard(void *p, size_t size) noexcept; #elif defined(_WIN32) #include -WritableBuffer +std::span HugeAllocate(size_t size); static inline void @@ -118,16 +118,16 @@ HugeDiscard(void *p, size_t size) noexcept #include -static inline WritableBuffer +static inline std::span 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 class HugeArray { - typedef WritableBuffer Buffer; + using Buffer = std::span; 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(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 diff --git a/src/util/SpanCast.hxx b/src/util/SpanCast.hxx new file mode 100644 index 000000000..a2cb624ce --- /dev/null +++ b/src/util/SpanCast.hxx @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Max Kellermann + * + * 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 +#include + +/** + * Cast a std::span to a std::span, rounding down to the + * next multiple of T's size. + */ +template +constexpr std::span +FromBytesFloor(std::span other) noexcept +{ + static_assert(sizeof(T) > 0, "Empty base type"); + + return { + reinterpret_cast(other.data()), + other.size() / sizeof(T), + }; +} diff --git a/src/util/SparseBuffer.hxx b/src/util/SparseBuffer.hxx index 7232609c3..9d16ee4fb 100644 --- a/src/util/SparseBuffer.hxx +++ b/src/util/SparseBuffer.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2018 Max Kellermann + * Copyright 2013-2022 Max Kellermann * * 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 #include @@ -118,7 +115,7 @@ public: struct ReadResult { size_type undefined_size; - ConstBuffer defined_buffer; + std::span 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 Write(size_type offset) noexcept { + std::span 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