diff --git a/NEWS b/NEWS index 00fbf0df26..57bbefc880 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ ver 0.25 (not yet released) * require Meson 1.2 ver 0.24.9 (not yet released) +* database + - upnp: refuse to build with libupnp >= 1.14.26 due to API breakage ver 0.24.8 (2026/01/26) * input diff --git a/meson.build b/meson.build index 07acfab5b7..934cb165bd 100644 --- a/meson.build +++ b/meson.build @@ -479,6 +479,7 @@ subdir('src/system') subdir('src/system/linux') subdir('src/thread') subdir('src/net') +subdir('src/memory') subdir('src/event') subdir('src/win32') @@ -642,6 +643,7 @@ mpd = build_target( zeroconf_dep, more_deps, chromaprint_dep, + memory_dep, fmt_dep, ], link_args: link_args, diff --git a/python/build/libs.py b/python/build/libs.py index fa90cc8e00..d0bc70e5c0 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -49,7 +49,7 @@ '--without-portaudio', '--without-portaudiocpp', '--without-sndfile', '--without-flac', ], - base='libopenmpt-0.8.3+release.autotools', + base='libopenmpt-0.8.4+release.autotools', ) wildmidi = CmakeProject( diff --git a/src/MusicBuffer.hxx b/src/MusicBuffer.hxx index 152d4b1b65..b509e092a8 100644 --- a/src/MusicBuffer.hxx +++ b/src/MusicBuffer.hxx @@ -6,7 +6,7 @@ #include "MusicChunk.hxx" #include "MusicChunkPtr.hxx" -#include "util/SliceBuffer.hxx" +#include "memory/SliceBuffer.hxx" #include "thread/Mutex.hxx" /** diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx index 4135efce89..be93405709 100644 --- a/src/input/AsyncInputStream.hxx +++ b/src/input/AsyncInputStream.hxx @@ -6,7 +6,7 @@ #include "InputStream.hxx" #include "thread/Cond.hxx" #include "event/InjectEvent.hxx" -#include "util/HugeAllocator.hxx" +#include "memory/HugeArray.hxx" #include "util/CircularBuffer.hxx" #include diff --git a/src/input/BufferingInputStream.hxx b/src/input/BufferingInputStream.hxx index a281f55cd9..f1f7e14992 100644 --- a/src/input/BufferingInputStream.hxx +++ b/src/input/BufferingInputStream.hxx @@ -8,7 +8,7 @@ #include "thread/Thread.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" -#include "util/SparseBuffer.hxx" +#include "memory/SparseBuffer.hxx" #include #include diff --git a/src/input/ThreadInputStream.hxx b/src/input/ThreadInputStream.hxx index e650f7a6e7..6ecfd1dec4 100644 --- a/src/input/ThreadInputStream.hxx +++ b/src/input/ThreadInputStream.hxx @@ -6,7 +6,7 @@ #include "InputStream.hxx" #include "thread/Thread.hxx" #include "thread/Cond.hxx" -#include "util/HugeAllocator.hxx" +#include "memory/HugeArray.hxx" #include "util/CircularBuffer.hxx" #include diff --git a/src/input/meson.build b/src/input/meson.build index b1f6b78b8f..ea161823c0 100644 --- a/src/input/meson.build +++ b/src/input/meson.build @@ -33,6 +33,7 @@ input_basic = static_library( input_api_dep, thread_dep, event_dep, + memory_dep, ], ) @@ -42,6 +43,7 @@ input_basic_dep = declare_dependency( input_api_dep, thread_dep, event_dep, + memory_dep, ], ) diff --git a/src/lib/upnp/meson.build b/src/lib/upnp/meson.build index 5af5326d45..9c2c7bac1f 100644 --- a/src/lib/upnp/meson.build +++ b/src/lib/upnp/meson.build @@ -12,12 +12,23 @@ endif if upnp_option == 'auto' upnp_dep = dependency('libupnp', version: '>= 1.8', required: false) + + if upnp_dep.found() and upnp_dep.version().version_compare('>= 1.14.26') + warning('Your libupnp version is known to be broken, see https://github.com/pupnp/pupnp/issues/528 - disabling') + upnp_dep = dependency('', required: false) + endif + conf.set('USING_PUPNP', upnp_dep.found()) if not upnp_dep.found() upnp_dep = dependency('libnpupnp', version: '>= 1.8', required: false) endif elif upnp_option == 'pupnp' upnp_dep = dependency('libupnp', version: '>= 1.8', required: true) + + if upnp_dep.found() and upnp_dep.version().version_compare('>= 1.14.26') + error('Your libupnp version is known to be broken, see https://github.com/pupnp/pupnp/issues/528') + endif + conf.set('USING_PUPNP', true) elif upnp_option == 'npupnp' upnp_dep = dependency('libnpupnp', required: true) diff --git a/src/memory/HugeAllocator.cxx b/src/memory/HugeAllocator.cxx new file mode 100644 index 0000000000..eda938bd76 --- /dev/null +++ b/src/memory/HugeAllocator.cxx @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause +// author: Max Kellermann + +#include "HugeAllocator.hxx" + +#ifdef __linux__ + +#include "system/PageAllocator.hxx" +#include "system/PageSize.hxx" +#include "system/VmaName.hxx" + +static std::span +AlignToPageSize(std::span p) noexcept +{ + return {p.data(), AlignToPageSize(p.size())}; +} + +std::span +HugeAllocate(size_t size) +{ + size = AlignToPageSize(size); + + const std::span p{AllocatePages(size), size}; + EnableHugePages(p); + return p; +} + +void +HugeFree(std::span p) noexcept +{ + FreePages(AlignToPageSize(p)); +} + +void +HugeSetName(std::span p, const char *name) noexcept +{ + SetVmaName(p.data(), p.size(), name); +} + +void +HugeForkCow(std::span p, bool enable) noexcept +{ + EnablePageFork(AlignToPageSize(p), enable); +} + +void +HugeDiscard(std::span p) noexcept +{ + DiscardPages(AlignToPageSize(p)); +} + +#elif defined(_WIN32) + +std::span +HugeAllocate(size_t size) +{ + // TODO: use MEM_LARGE_PAGES + void *p = VirtualAlloc(nullptr, size, + MEM_COMMIT|MEM_RESERVE, + PAGE_READWRITE); + if (p == nullptr) + throw std::bad_alloc(); + + // TODO: round size up to the page size + return {(std::byte *)p, size}; +} + +#endif diff --git a/src/memory/HugeAllocator.hxx b/src/memory/HugeAllocator.hxx new file mode 100644 index 0000000000..b9c22b0c12 --- /dev/null +++ b/src/memory/HugeAllocator.hxx @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +// author: Max Kellermann + +#pragma once + +#include +#include + +#ifdef __linux__ + +/** + * Allocate a huge amount of memory. This will be done in a way that + * allows giving the memory back to the kernel as soon as we don't + * need it anymore. On the downside, this call is expensive. + * + * Throws std::bad_alloc on error + * + * @returns the allocated buffer with a size which may be rounded up + * (to the next page size), so callers can take advantage of this + * allocation overhead + */ +std::span +HugeAllocate(size_t size); + +/** + * @param p an allocation returned by HugeAllocate() + */ +void +HugeFree(std::span p) noexcept; + +/** + * Set a name for the specified virtual memory area. + * + * This feature requires Linux 5.17. + */ +void +HugeSetName(std::span p, const char *name) noexcept; + +/** + * Control whether this allocation is copied to newly forked child + * processes. Disabling that makes forking a little bit cheaper. + */ +void +HugeForkCow(std::span p, bool enable) noexcept; + +/** + * Discard any data stored in the allocation and give the memory back + * to the kernel. After returning, the allocation still exists and + * can be reused at any time, but its contents are undefined. + * + * @param p an allocation returned by HugeAllocate() + */ +void +HugeDiscard(std::span p) noexcept; + +#elif defined(_WIN32) +#include + +std::span +HugeAllocate(size_t size); + +static inline void +HugeFree(std::span p) noexcept +{ + VirtualFree(p.data(), 0, MEM_RELEASE); +} + +static inline void +HugeSetName(std::span, const char *) noexcept +{ +} + +static inline void +HugeForkCow(std::span, bool) noexcept +{ +} + +static inline void +HugeDiscard(std::span p) noexcept +{ + VirtualAlloc(p.data(), p.size(), MEM_RESET, PAGE_NOACCESS); +} + +#else + +/* not Linux: fall back to standard C calls */ + +#include + +static inline std::span +HugeAllocate(size_t size) +{ + return {new std::byte[size], size}; +} + +static inline void +HugeFree(std::span p) noexcept +{ + delete[] p.data(); +} + +static inline void +HugeSetName(std::span, const char *) noexcept +{ +} + +static inline void +HugeForkCow(std::span, bool) noexcept +{ +} + +static inline void +HugeDiscard(std::span) noexcept +{ +} + +#endif diff --git a/src/memory/HugeArray.hxx b/src/memory/HugeArray.hxx new file mode 100644 index 0000000000..ff59f7dd5d --- /dev/null +++ b/src/memory/HugeArray.hxx @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BSD-2-Clause +// author: Max Kellermann + +#pragma once + +#include "HugeAllocator.hxx" +#include "util/SpanCast.hxx" + +#include + +/** + * Automatic memory management for a dynamic array in "huge" memory. + */ +template +class HugeArray { + using Buffer = std::span; + Buffer buffer; + +public: + typedef typename Buffer::size_type size_type; + typedef typename Buffer::value_type value_type; + typedef typename Buffer::reference reference; + typedef typename Buffer::const_reference const_reference; + typedef typename Buffer::iterator iterator; + + constexpr HugeArray() noexcept = default; + + explicit HugeArray(size_type _size) + :buffer(FromBytesFloor(HugeAllocate(sizeof(value_type) * _size))) {} + + constexpr HugeArray(HugeArray &&other) noexcept + :buffer(std::exchange(other.buffer, nullptr)) {} + + ~HugeArray() noexcept { + if (!buffer.empty()) { + HugeFree(std::as_writable_bytes(buffer)); + } + } + + constexpr HugeArray &operator=(HugeArray &&other) noexcept { + using std::swap; + swap(buffer, other.buffer); + return *this; + } + + void SetName(const char *name) noexcept { + HugeSetName(std::as_writable_bytes(buffer), name); + } + + void ForkCow(bool enable) noexcept { + HugeForkCow(std::as_writable_bytes(buffer), enable); + } + + void Discard() noexcept { + HugeDiscard(std::as_writable_bytes(buffer)); + } + + constexpr bool operator==(std::nullptr_t) const noexcept { + return buffer == nullptr; + } + + constexpr bool operator!=(std::nullptr_t) const noexcept { + return buffer != nullptr; + } + + constexpr operator std::span() noexcept { + return buffer; + } + + constexpr operator std::span() const noexcept { + return buffer; + } + + /** + * Returns the number of allocated elements. + */ + constexpr size_type size() const noexcept { + return buffer.size(); + } + + constexpr reference front() noexcept { + return buffer.front(); + } + + constexpr const_reference front() const noexcept { + return buffer.front(); + } + + constexpr reference back() noexcept { + return buffer.back(); + } + + constexpr const_reference back() const noexcept { + return buffer.back(); + } + + /** + * Returns one element. No bounds checking. + */ + constexpr reference operator[](size_type i) noexcept { + return buffer[i]; + } + + /** + * Returns one constant element. No bounds checking. + */ + constexpr const_reference operator[](size_type i) const noexcept { + return buffer[i]; + } + + constexpr iterator begin() noexcept { + return buffer.begin(); + } + + constexpr auto begin() const noexcept { + return buffer.begin(); + } + + constexpr iterator end() noexcept { + return buffer.end(); + } + + constexpr auto end() const noexcept { + return buffer.end(); + } +}; diff --git a/src/util/SliceBuffer.hxx b/src/memory/SliceBuffer.hxx similarity index 96% rename from src/util/SliceBuffer.hxx rename to src/memory/SliceBuffer.hxx index c7d593b061..f93089e96d 100644 --- a/src/util/SliceBuffer.hxx +++ b/src/memory/SliceBuffer.hxx @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Copyright The Music Player Daemon Project -#ifndef MPD_SLICE_BUFFER_HXX -#define MPD_SLICE_BUFFER_HXX +#pragma once -#include "HugeAllocator.hxx" +#include "HugeArray.hxx" #include #include @@ -129,5 +128,3 @@ public: } } }; - -#endif diff --git a/src/util/SparseBuffer.cxx b/src/memory/SparseBuffer.cxx similarity index 100% rename from src/util/SparseBuffer.cxx rename to src/memory/SparseBuffer.cxx diff --git a/src/util/SparseBuffer.hxx b/src/memory/SparseBuffer.hxx similarity index 98% rename from src/util/SparseBuffer.hxx rename to src/memory/SparseBuffer.hxx index 095d066755..c734d91c4e 100644 --- a/src/util/SparseBuffer.hxx +++ b/src/memory/SparseBuffer.hxx @@ -3,7 +3,7 @@ #pragma once -#include "HugeAllocator.hxx" +#include "HugeArray.hxx" #include #include diff --git a/src/memory/meson.build b/src/memory/meson.build new file mode 100644 index 0000000000..f68770593a --- /dev/null +++ b/src/memory/meson.build @@ -0,0 +1,17 @@ +memory = static_library( + 'memory', + 'HugeAllocator.cxx', + 'SparseBuffer.cxx', + include_directories: inc, + dependencies: [ + util_dep, + system_dep, + ], +) + +memory_dep = declare_dependency( + link_with: memory, + dependencies: [ + util_dep, + ], +) diff --git a/src/system/PageAllocator.cxx b/src/system/PageAllocator.cxx new file mode 100644 index 0000000000..8ec42149ec --- /dev/null +++ b/src/system/PageAllocator.cxx @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann + +#include "PageAllocator.hxx" + +#include + +std::byte * +AllocatePages(std::size_t size) +{ + void *p = mmap(NULL, size, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + if (p == MAP_FAILED) + throw std::bad_alloc{}; + + return reinterpret_cast(p); +} diff --git a/src/system/PageAllocator.hxx b/src/system/PageAllocator.hxx new file mode 100644 index 0000000000..7016a8e883 --- /dev/null +++ b/src/system/PageAllocator.hxx @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright CM4all GmbH +// author: Max Kellermann + +#pragma once + +#include +#include + +#include + +/** + * Allocate pages from the kernel + * + * Throws std::bad_alloc on error. + * + * @param size the size of the allocation; must be a multiple of + * #PAGE_SIZE + */ +std::byte * +AllocatePages(std::size_t size); + +static inline void +FreePages(std::span p) noexcept +{ + munmap(p.data(), p.size()); +} + +/** + * Allow the Linux kernel to use "Huge Pages" for the cache, which + * reduces page table overhead for this big chunk of data. + * + * @param size a multiple of #HUGE_PAGE_SIZE + */ +static inline void +EnableHugePages(std::span p) noexcept +{ +#ifdef MADV_HUGEPAGE + madvise(p.data(), p.size(), MADV_HUGEPAGE); +#else + (void)p; +#endif +} + +/** + * Attempt to collapse all regular pages into transparent huge pages. + * + * @param size a multiple of #HUGE_PAGE_SIZE + */ +static inline void +CollapseHugePages(std::span p) noexcept +{ +#ifdef MADV_COLLAPSE + madvise(p.data(), p.size(), MADV_COLLAPSE); +#else + (void)p; +#endif +} + +/** + * Controls whether forked processes inherit the specified pages. + */ +static inline void +EnablePageFork(std::span p, bool inherit) noexcept +{ +#ifdef __linux__ + madvise(p.data(), p.size(), inherit ? MADV_DOFORK : MADV_DONTFORK); +#else + (void)p; + (void)inherit; +#endif +} + +/** + * Controls whether the specified pages will be included in a core + * dump. + */ +static inline void +EnablePageDump(std::span p, bool dump) noexcept +{ +#ifdef __linux__ + madvise(p.data(), p.size(), dump ? MADV_DODUMP : MADV_DONTDUMP); +#else + (void)p; + (void)dump; +#endif +} + +/** + * Discard the specified page contents, giving memory back to the + * kernel. The mapping is preserved, and new memory will be allocated + * automatically on the next write access. + */ +static inline void +DiscardPages(std::span p) noexcept +{ +#ifdef __linux__ + madvise(p.data(), p.size(), MADV_DONTNEED); +#else + (void)p; +#endif +} + +/** + * Populate (prefault) page tables writable, faulting in all pages in + * the range just as if manually writing to each each page. + */ +static inline void +PagesPopulateWrite(std::span p) noexcept +{ +#ifdef MADV_POPULATE_WRITE + madvise(p.data(), p.size(), MADV_POPULATE_WRITE); +#else + (void)p; +#endif +} diff --git a/src/system/PageSize.hxx b/src/system/PageSize.hxx new file mode 100644 index 0000000000..8c9ac3c85b --- /dev/null +++ b/src/system/PageSize.hxx @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-2-Clause +// author: Max Kellermann + +#pragma once + +#include "util/RoundPowerOfTwo.hxx" + +#include + +#include // for sysconf() + +/** + * Round up the parameter, make it page-aligned. + */ +[[gnu::const]] +static std::size_t +AlignToPageSize(std::size_t size) noexcept +{ + static const long page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) + return size; + + return RoundUpToPowerOfTwo(size, static_cast(page_size)); +} diff --git a/src/system/meson.build b/src/system/meson.build index afcb32b4bb..063dbabe35 100644 --- a/src/system/meson.build +++ b/src/system/meson.build @@ -8,6 +8,7 @@ if host_machine.system() == 'linux' 'EventFD.cxx', 'SignalFD.cxx', 'EpollFD.cxx', + 'PageAllocator.cxx', ] endif diff --git a/src/util/HugeAllocator.cxx b/src/util/HugeAllocator.cxx deleted file mode 100644 index bc5aeff273..0000000000 --- a/src/util/HugeAllocator.cxx +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -// author: Max Kellermann - -#include "HugeAllocator.hxx" -#include "system/VmaName.hxx" -#include "util/RoundPowerOfTwo.hxx" - -#include - -#ifdef __linux__ -#include -#include -#else -#include -#endif - -#ifdef __linux__ - -/** - * Round up the parameter, make it page-aligned. - */ -[[gnu::const]] -static size_t -AlignToPageSize(size_t size) noexcept -{ - static const long page_size = sysconf(_SC_PAGESIZE); - if (page_size <= 0) - return size; - - return RoundUpToPowerOfTwo(size, static_cast(page_size)); -} - -std::span -HugeAllocate(size_t size) -{ - size = AlignToPageSize(size); - - constexpr int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE; - void *p = mmap(nullptr, size, - PROT_READ|PROT_WRITE, flags, - -1, 0); - if (p == (void *)-1) - throw std::bad_alloc(); - -#ifdef MADV_HUGEPAGE - /* allow the Linux kernel to use "Huge Pages", which reduces page - table overhead for this big chunk of data */ - madvise(p, size, MADV_HUGEPAGE); -#endif - - return {(std::byte *)p, size}; -} - -void -HugeFree(void *p, size_t size) noexcept -{ - munmap(p, AlignToPageSize(size)); -} - -void -HugeSetName(void *p, size_t size, const char *name) noexcept -{ - SetVmaName(p, size, name); -} - -void -HugeForkCow(void *p, size_t size, bool enable) noexcept -{ -#ifdef MADV_DONTFORK - madvise(p, AlignToPageSize(size), - enable ? MADV_DOFORK : MADV_DONTFORK); -#endif -} - -void -HugeDiscard(void *p, size_t size) noexcept -{ -#ifdef MADV_DONTNEED - madvise(p, AlignToPageSize(size), MADV_DONTNEED); -#endif -} - -#elif defined(_WIN32) - -std::span -HugeAllocate(size_t size) -{ - // TODO: use MEM_LARGE_PAGES - void *p = VirtualAlloc(nullptr, size, - MEM_COMMIT|MEM_RESERVE, - PAGE_READWRITE); - if (p == nullptr) - throw std::bad_alloc(); - - // TODO: round size up to the page size - return {(std::byte *)p, size}; -} - -#endif diff --git a/src/util/HugeAllocator.hxx b/src/util/HugeAllocator.hxx deleted file mode 100644 index 1720080af7..0000000000 --- a/src/util/HugeAllocator.hxx +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -// author: Max Kellermann - -#pragma once - -#include "SpanCast.hxx" - -#include -#include -#include - -#ifdef __linux__ - -/** - * Allocate a huge amount of memory. This will be done in a way that - * allows giving the memory back to the kernel as soon as we don't - * need it anymore. On the downside, this call is expensive. - * - * Throws std::bad_alloc on error - * - * @returns the allocated buffer with a size which may be rounded up - * (to the next page size), so callers can take advantage of this - * allocation overhead - */ -std::span -HugeAllocate(size_t size); - -/** - * @param p an allocation returned by HugeAllocate() - * @param size the allocation's size as passed to HugeAllocate() - */ -void -HugeFree(void *p, size_t size) noexcept; - -/** - * Set a name for the specified virtual memory area. - * - * This feature requires Linux 5.17. - */ -void -HugeSetName(void *p, size_t size, const char *name) noexcept; - -/** - * Control whether this allocation is copied to newly forked child - * processes. Disabling that makes forking a little bit cheaper. - */ -void -HugeForkCow(void *p, size_t size, bool enable) noexcept; - -/** - * Discard any data stored in the allocation and give the memory back - * to the kernel. After returning, the allocation still exists and - * can be reused at any time, but its contents are undefined. - * - * @param p an allocation returned by HugeAllocate() - * @param size the allocation's size as passed to HugeAllocate() - */ -void -HugeDiscard(void *p, size_t size) noexcept; - -#elif defined(_WIN32) -#include - -std::span -HugeAllocate(size_t size); - -static inline void -HugeFree(void *p, size_t) noexcept -{ - VirtualFree(p, 0, MEM_RELEASE); -} - -static inline void -HugeSetName(void *, size_t, const char *) noexcept -{ -} - -static inline void -HugeForkCow(void *, size_t, bool) noexcept -{ -} - -static inline void -HugeDiscard(void *p, size_t size) noexcept -{ - VirtualAlloc(p, size, MEM_RESET, PAGE_NOACCESS); -} - -#else - -/* not Linux: fall back to standard C calls */ - -#include - -static inline std::span -HugeAllocate(size_t size) -{ - return {new std::byte[size], size}; -} - -static inline void -HugeFree(void *_p, size_t) noexcept -{ - auto *p = (std::byte *)_p; - delete[] p; -} - -static inline void -HugeSetName(void *, size_t, const char *) noexcept -{ -} - -static inline void -HugeForkCow(void *, size_t, bool) noexcept -{ -} - -static inline void -HugeDiscard(void *, size_t) noexcept -{ -} - -#endif - -/** - * Automatic memory management for a dynamic array in "huge" memory. - */ -template -class HugeArray { - using Buffer = std::span; - Buffer buffer; - -public: - typedef typename Buffer::size_type size_type; - typedef typename Buffer::value_type value_type; - typedef typename Buffer::reference reference; - typedef typename Buffer::const_reference const_reference; - typedef typename Buffer::iterator iterator; - - constexpr HugeArray() noexcept = default; - - explicit HugeArray(size_type _size) - :buffer(FromBytesFloor(HugeAllocate(sizeof(value_type) * _size))) {} - - constexpr HugeArray(HugeArray &&other) noexcept - :buffer(std::exchange(other.buffer, nullptr)) {} - - ~HugeArray() noexcept { - if (!buffer.empty()) { - auto v = std::as_writable_bytes(buffer); - HugeFree(v.data(), v.size()); - } - } - - constexpr HugeArray &operator=(HugeArray &&other) noexcept { - using std::swap; - swap(buffer, other.buffer); - return *this; - } - - void SetName(const char *name) noexcept { - const auto v = std::as_writable_bytes(buffer); - HugeSetName(v.data(), v.size(), name); - } - - void ForkCow(bool enable) noexcept { - const auto v = std::as_writable_bytes(buffer); - HugeForkCow(v.data(), v.size(), enable); - } - - void Discard() noexcept { - const auto v = std::as_writable_bytes(buffer); - HugeDiscard(v.data(), v.size()); - } - - constexpr bool operator==(std::nullptr_t) const noexcept { - return buffer == nullptr; - } - - constexpr bool operator!=(std::nullptr_t) const noexcept { - return buffer != nullptr; - } - - constexpr operator std::span() noexcept { - return buffer; - } - - constexpr operator std::span() noexcept { - return buffer; - } - - /** - * Returns the number of allocated elements. - */ - constexpr size_type size() const noexcept { - return buffer.size(); - } - - constexpr reference front() noexcept { - return buffer.front(); - } - - constexpr const_reference front() const noexcept { - return buffer.front(); - } - - constexpr reference back() noexcept { - return buffer.back(); - } - - constexpr const_reference back() const noexcept { - return buffer.back(); - } - - /** - * Returns one element. No bounds checking. - */ - constexpr reference operator[](size_type i) noexcept { - return buffer[i]; - } - - /** - * Returns one constant element. No bounds checking. - */ - constexpr const_reference operator[](size_type i) const noexcept { - return buffer[i]; - } - - constexpr iterator begin() noexcept { - return buffer.begin(); - } - - constexpr auto begin() const noexcept { - return buffer.begin(); - } - - constexpr iterator end() noexcept { - return buffer.end(); - } - - constexpr auto end() const noexcept { - return buffer.end(); - } -}; diff --git a/src/util/meson.build b/src/util/meson.build index 144f5db450..6a36987407 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -15,10 +15,8 @@ util = static_library( 'UriRelative.cxx', 'UriUtil.cxx', 'LazyRandomEngine.cxx', - 'HugeAllocator.cxx', 'PeakBuffer.cxx', 'PrintException.cxx', - 'SparseBuffer.cxx', 'ByteReverse.cxx', 'format.c', 'BitReverse.cxx', diff --git a/subprojects/sqlite3.wrap b/subprojects/sqlite3.wrap index 5f21fb00ed..77fae8e774 100644 --- a/subprojects/sqlite3.wrap +++ b/subprojects/sqlite3.wrap @@ -1,13 +1,14 @@ [wrap-file] -directory = sqlite-amalgamation-3510100 -source_url = https://www.sqlite.org/2025/sqlite-amalgamation-3510100.zip -source_filename = sqlite-amalgamation-3510100.zip -source_hash = 84a85d6a1b920234349f01720912c12391a4f0cb5cb998087e641dee3ef8ef2e -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.51.1-1/sqlite-amalgamation-3510100.zip -patch_filename = sqlite3_3.51.1-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.1-1/get_patch -patch_hash = 081f7997f22175049ebfa463f876fbd707352fafdb87c13638990cd99656ef15 -wrapdb_version = 3.51.1-1 +directory = sqlite-amalgamation-3510200 +source_url = https://www.sqlite.org/2026/sqlite-amalgamation-3510200.zip +source_filename = sqlite-amalgamation-3510200.zip +source_hash = 6e2a845a493026bdbad0618b2b5a0cf48584faab47384480ed9f592d912f23ec +source_fallback_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.2-1/get_source/sqlite-amalgamation-3510200.zip +patch_filename = sqlite3_3.51.2-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.2-1/get_patch +patch_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.51.2-1/sqlite3_3.51.2-1_patch.zip +patch_hash = eef624e9916ec7b7c62dccbf1a04a8bc6fdcacfb5b58daaba695c204e00bec67 +wrapdb_version = 3.51.2-1 [provide] dependency_names = sqlite3