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);
void *p = HugeAllocate(buffer_size);
assert(p != nullptr);
auto allocation = HugeAllocate(buffer_size);
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();
}

View File

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

View File

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

View File

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