util/HugeAllocator: HugeAllocator() returns WritableBuffer<void>

This commit is contained in:
Max Kellermann 2017-09-21 20:31:03 +02:00
parent 3e5ce3c92c
commit b46835e15e
4 changed files with 32 additions and 30 deletions

View File

@ -50,12 +50,13 @@ ThreadInputStream::Start()
{ {
assert(buffer == nullptr); assert(buffer == nullptr);
void *p = HugeAllocate(buffer_size); auto allocation = HugeAllocate(buffer_size);
assert(p != nullptr); assert(allocation != nullptr);
HugeForkCow(p, buffer_size, false); HugeForkCow(allocation.data, allocation.size, false);
buffer = new CircularBuffer<uint8_t>((uint8_t *)p, buffer_size); buffer = new CircularBuffer<uint8_t>((uint8_t *)allocation.data,
allocation.size);
thread.Start(); thread.Start();
} }

View File

@ -55,7 +55,7 @@ AlignToPageSize(size_t size) noexcept
return (size + ps - 1) / ps * ps; return (size + ps - 1) / ps * ps;
} }
void * WritableBuffer<void>
HugeAllocate(size_t size) HugeAllocate(size_t size)
{ {
size = AlignToPageSize(size); size = AlignToPageSize(size);
@ -73,7 +73,7 @@ HugeAllocate(size_t size)
madvise(p, size, MADV_HUGEPAGE); madvise(p, size, MADV_HUGEPAGE);
#endif #endif
return p; return {p, size};
} }
void void
@ -101,7 +101,7 @@ HugeDiscard(void *p, size_t size) noexcept
#elif defined(WIN32) #elif defined(WIN32)
void * WritableBuffer<void>
HugeAllocate(size_t size) HugeAllocate(size_t size)
{ {
// TODO: use MEM_LARGE_PAGES // TODO: use MEM_LARGE_PAGES
@ -111,7 +111,8 @@ HugeAllocate(size_t size)
if (p == nullptr) if (p == nullptr)
throw std::bad_alloc(); throw std::bad_alloc();
return p; // TODO: round size up to the page size
return {p, size};
} }
#endif #endif

View File

@ -30,6 +30,7 @@
#ifndef HUGE_ALLOCATOR_HXX #ifndef HUGE_ALLOCATOR_HXX
#define HUGE_ALLOCATOR_HXX #define HUGE_ALLOCATOR_HXX
#include "WritableBuffer.hxx"
#include "Compiler.h" #include "Compiler.h"
#include <utility> #include <utility>
@ -44,9 +45,12 @@
* need it anymore. On the downside, this call is expensive. * need it anymore. On the downside, this call is expensive.
* *
* Throws std::bad_alloc on error * 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
*/ */
gcc_malloc WritableBuffer<void>
void *
HugeAllocate(size_t size); HugeAllocate(size_t size);
/** /**
@ -77,8 +81,7 @@ HugeDiscard(void *p, size_t size) noexcept;
#elif defined(WIN32) #elif defined(WIN32)
#include <windows.h> #include <windows.h>
gcc_malloc WritableBuffer<void>
void *
HugeAllocate(size_t size); HugeAllocate(size_t size);
static inline void static inline void
@ -104,11 +107,10 @@ HugeDiscard(void *p, size_t size) noexcept
#include <stdint.h> #include <stdint.h>
gcc_malloc WritableBuffer<void>
static inline void *
HugeAllocate(size_t size) HugeAllocate(size_t size)
{ {
return new uint8_t[size]; return {new uint8_t[size], size};
} }
static inline void static inline void
@ -134,46 +136,44 @@ HugeDiscard(void *, size_t) noexcept
* Automatic huge memory allocation management. * Automatic huge memory allocation management.
*/ */
class HugeAllocation { class HugeAllocation {
void *data = nullptr; WritableBuffer<void> buffer = nullptr;
size_t size;
public: public:
HugeAllocation() = default; HugeAllocation() = default;
explicit HugeAllocation(size_t _size) explicit HugeAllocation(size_t _size)
:data(HugeAllocate(_size)), size(_size) {} :buffer(HugeAllocate(_size)) {}
HugeAllocation(HugeAllocation &&src) noexcept HugeAllocation(HugeAllocation &&src) noexcept
:data(std::exchange(src.data, nullptr)), size(src.size) {} :buffer(std::exchange(src.buffer, nullptr)) {}
~HugeAllocation() { ~HugeAllocation() {
if (data != nullptr) if (buffer != nullptr)
HugeFree(data, size); HugeFree(buffer.data, buffer.size);
} }
HugeAllocation &operator=(HugeAllocation &&src) noexcept { HugeAllocation &operator=(HugeAllocation &&src) noexcept {
std::swap(data, src.data); std::swap(buffer, src.buffer);
std::swap(size, src.size);
return *this; return *this;
} }
void ForkCow(bool enable) noexcept { void ForkCow(bool enable) noexcept {
HugeForkCow(data, size, enable); HugeForkCow(buffer.data, buffer.size, enable);
} }
void Discard() noexcept { void Discard() noexcept {
HugeDiscard(data, size); HugeDiscard(buffer.data, buffer.size);
} }
void reset() noexcept { void reset() noexcept {
if (data != nullptr) { if (buffer != nullptr) {
HugeFree(data, size); HugeFree(buffer.data, buffer.size);
data = nullptr; buffer = nullptr;
} }
} }
void *get() noexcept { void *get() noexcept {
return data; return buffer.data;
} }
}; };

View File

@ -72,7 +72,7 @@ class SliceBuffer {
public: public:
SliceBuffer(unsigned _count) SliceBuffer(unsigned _count)
:n_max(_count), :n_max(_count),
data((Slice *)HugeAllocate(CalcAllocationSize())) { data((Slice *)HugeAllocate(CalcAllocationSize()).data) {
assert(n_max > 0); assert(n_max > 0);
HugeForkCow(data, CalcAllocationSize(), false); HugeForkCow(data, CalcAllocationSize(), false);