util/HugeAllocator: throw std::bad_alloc on error
This commit is contained in:
parent
35faafb32c
commit
ef053035d0
|
@ -20,14 +20,11 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "MusicBuffer.hxx"
|
#include "MusicBuffer.hxx"
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
||||||
:buffer(num_chunks) {
|
:buffer(num_chunks) {
|
||||||
if (buffer.IsOOM())
|
|
||||||
FatalError("Failed to allocate buffer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicChunk *
|
MusicChunk *
|
||||||
|
|
|
@ -50,10 +50,7 @@ ThreadInputStream::Start(Error &error)
|
||||||
assert(buffer == nullptr);
|
assert(buffer == nullptr);
|
||||||
|
|
||||||
void *p = HugeAllocate(buffer_size);
|
void *p = HugeAllocate(buffer_size);
|
||||||
if (p == nullptr) {
|
assert(p != nullptr);
|
||||||
error.SetErrno();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = new CircularBuffer<uint8_t>((uint8_t *)p, buffer_size);
|
buffer = new CircularBuffer<uint8_t>((uint8_t *)p, buffer_size);
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,10 @@ struct CurlInputStream final : public AsyncInputStream {
|
||||||
/** parser for icy-metadata */
|
/** parser for icy-metadata */
|
||||||
IcyInputStream *icy;
|
IcyInputStream *icy;
|
||||||
|
|
||||||
CurlInputStream(const char *_url, Mutex &_mutex, Cond &_cond,
|
CurlInputStream(const char *_url, Mutex &_mutex, Cond &_cond)
|
||||||
void *_buffer)
|
|
||||||
:AsyncInputStream(_url, _mutex, _cond,
|
:AsyncInputStream(_url, _mutex, _cond,
|
||||||
_buffer, CURL_MAX_BUFFERED,
|
HugeAllocate(CURL_MAX_BUFFERED),
|
||||||
|
CURL_MAX_BUFFERED,
|
||||||
CURL_RESUME_AT),
|
CURL_RESUME_AT),
|
||||||
request_headers(nullptr),
|
request_headers(nullptr),
|
||||||
icy(new IcyInputStream(this)) {}
|
icy(new IcyInputStream(this)) {}
|
||||||
|
@ -844,14 +844,7 @@ inline InputStream *
|
||||||
CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond,
|
CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond,
|
||||||
Error &error)
|
Error &error)
|
||||||
{
|
{
|
||||||
void *buffer = HugeAllocate(CURL_MAX_BUFFERED);
|
CurlInputStream *c = new CurlInputStream(url, mutex, cond);
|
||||||
if (buffer == nullptr) {
|
|
||||||
error.Set(curl_domain, "Out of memory");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurlInputStream *c = new CurlInputStream(url, mutex, cond, buffer);
|
|
||||||
|
|
||||||
if (!c->InitEasy(error) || !input_curl_easy_add_indirect(c, error)) {
|
if (!c->InitEasy(error) || !input_curl_easy_add_indirect(c, error)) {
|
||||||
delete c;
|
delete c;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -48,11 +48,10 @@ class NfsInputStream final : public AsyncInputStream, NfsFileReader {
|
||||||
bool reconnect_on_resume, reconnecting;
|
bool reconnect_on_resume, reconnecting;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NfsInputStream(const char *_uri,
|
NfsInputStream(const char *_uri, Mutex &_mutex, Cond &_cond)
|
||||||
Mutex &_mutex, Cond &_cond,
|
|
||||||
void *_buffer)
|
|
||||||
:AsyncInputStream(_uri, _mutex, _cond,
|
:AsyncInputStream(_uri, _mutex, _cond,
|
||||||
_buffer, NFS_MAX_BUFFERED,
|
HugeAllocate(NFS_MAX_BUFFERED),
|
||||||
|
NFS_MAX_BUFFERED,
|
||||||
NFS_RESUME_AT),
|
NFS_RESUME_AT),
|
||||||
reconnect_on_resume(false), reconnecting(false) {}
|
reconnect_on_resume(false), reconnecting(false) {}
|
||||||
|
|
||||||
|
@ -239,13 +238,7 @@ input_nfs_open(const char *uri,
|
||||||
if (!StringStartsWith(uri, "nfs://"))
|
if (!StringStartsWith(uri, "nfs://"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
void *buffer = HugeAllocate(NFS_MAX_BUFFERED);
|
NfsInputStream *is = new NfsInputStream(uri, mutex, cond);
|
||||||
if (buffer == nullptr) {
|
|
||||||
error.Set(nfs_domain, "Out of memory");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NfsInputStream *is = new NfsInputStream(uri, mutex, cond, buffer);
|
|
||||||
if (!is->Open(error)) {
|
if (!is->Open(error)) {
|
||||||
delete is;
|
delete is;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Max Kellermann <max@duempel.org>
|
* Copyright (C) 2013-2016 Max Kellermann <max@duempel.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -54,7 +54,7 @@ AlignToPageSize(size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
HugeAllocate(size_t size)
|
HugeAllocate(size_t size) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
size = AlignToPageSize(size);
|
size = AlignToPageSize(size);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ HugeAllocate(size_t size)
|
||||||
PROT_READ|PROT_WRITE, flags,
|
PROT_READ|PROT_WRITE, flags,
|
||||||
-1, 0);
|
-1, 0);
|
||||||
if (p == (void *)-1)
|
if (p == (void *)-1)
|
||||||
return nullptr;
|
throw std::bad_alloc();
|
||||||
|
|
||||||
#ifdef MADV_HUGEPAGE
|
#ifdef MADV_HUGEPAGE
|
||||||
/* allow the Linux kernel to use "Huge Pages", which reduces page
|
/* allow the Linux kernel to use "Huge Pages", which reduces page
|
||||||
|
@ -94,4 +94,19 @@ HugeDiscard(void *p, size_t size)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(WIN32)
|
||||||
|
|
||||||
|
void *
|
||||||
|
HugeAllocate(size_t size) throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
// TODO: use MEM_LARGE_PAGES
|
||||||
|
void *p = VirtualAlloc(nullptr, size,
|
||||||
|
MEM_COMMIT|MEM_RESERVE,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (p == nullptr)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Max Kellermann <max@duempel.org>
|
* Copyright (C) 2013-2016 Max Kellermann <max@duempel.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -43,7 +45,7 @@
|
||||||
*/
|
*/
|
||||||
gcc_malloc
|
gcc_malloc
|
||||||
void *
|
void *
|
||||||
HugeAllocate(size_t size);
|
HugeAllocate(size_t size) throw(std::bad_alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param p an allocation returned by HugeAllocate()
|
* @param p an allocation returned by HugeAllocate()
|
||||||
|
@ -67,14 +69,8 @@ HugeDiscard(void *p, size_t size);
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
gcc_malloc
|
gcc_malloc
|
||||||
static inline void *
|
void *
|
||||||
HugeAllocate(size_t size)
|
HugeAllocate(size_t size) throw(std::bad_alloc);
|
||||||
{
|
|
||||||
// TODO: use MEM_LARGE_PAGES
|
|
||||||
return VirtualAlloc(nullptr, size,
|
|
||||||
MEM_COMMIT|MEM_RESERVE,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
HugeFree(void *p, gcc_unused size_t size)
|
HugeFree(void *p, gcc_unused size_t size)
|
||||||
|
@ -92,19 +88,20 @@ HugeDiscard(void *p, size_t size)
|
||||||
|
|
||||||
/* not Linux: fall back to standard C calls */
|
/* not Linux: fall back to standard C calls */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
gcc_malloc
|
gcc_malloc
|
||||||
static inline void *
|
static inline void *
|
||||||
HugeAllocate(size_t size)
|
HugeAllocate(size_t size) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return new uint8_t[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
HugeFree(void *p, size_t)
|
HugeFree(void *_p, size_t)
|
||||||
{
|
{
|
||||||
free(p);
|
auto *p = (uint8_t *)_p;
|
||||||
|
delete[] p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
@ -88,13 +88,6 @@ public:
|
||||||
SliceBuffer(const SliceBuffer &other) = delete;
|
SliceBuffer(const SliceBuffer &other) = delete;
|
||||||
SliceBuffer &operator=(const SliceBuffer &other) = delete;
|
SliceBuffer &operator=(const SliceBuffer &other) = delete;
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if buffer allocation (by the constructor) has failed
|
|
||||||
*/
|
|
||||||
bool IsOOM() {
|
|
||||||
return data == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned GetCapacity() const {
|
unsigned GetCapacity() const {
|
||||||
return n_max;
|
return n_max;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue