aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/MusicBuffer.cxx6
-rw-r--r--src/util/SliceBuffer.hxx27
2 files changed, 28 insertions, 5 deletions
diff --git a/src/MusicBuffer.cxx b/src/MusicBuffer.cxx
index ec6e52054..5fddddc22 100644
--- a/src/MusicBuffer.cxx
+++ b/src/MusicBuffer.cxx
@@ -21,6 +21,7 @@
#include "MusicBuffer.hxx"
#include "MusicChunk.hxx"
#include "util/SliceBuffer.hxx"
+#include "mpd_error.h"
#include <glib.h>
@@ -32,7 +33,10 @@ struct music_buffer : public SliceBuffer<music_chunk> {
music_buffer(unsigned num_chunks)
:SliceBuffer(num_chunks),
- mutex(g_mutex_new()) {}
+ mutex(g_mutex_new()) {
+ if (IsOOM())
+ MPD_ERROR("Failed to allocate buffer");
+ }
~music_buffer() {
g_mutex_free(mutex);
diff --git a/src/util/SliceBuffer.hxx b/src/util/SliceBuffer.hxx
index 1f5ff873d..c61f164f4 100644
--- a/src/util/SliceBuffer.hxx
+++ b/src/util/SliceBuffer.hxx
@@ -20,10 +20,9 @@
#ifndef MPD_SLICE_BUFFER_HXX
#define MPD_SLICE_BUFFER_HXX
+#include "HugeAllocator.hxx"
#include "gcc.h"
-#include <glib.h>
-
#include <utility>
#include <new>
@@ -66,10 +65,15 @@ class SliceBuffer {
*/
Slice *available;
+ size_t CalcAllocationSize() const {
+ return n_max * sizeof(Slice);
+ }
+
public:
SliceBuffer(unsigned _count)
:n_max(_count), n_initialized(0), n_allocated(0),
- data(g_new(Slice, n_max)), available(nullptr) {
+ data((Slice *)HugeAllocate(CalcAllocationSize())),
+ available(nullptr) {
assert(n_max > 0);
}
@@ -78,12 +82,19 @@ public:
assertion checks for leaks */
assert(n_allocated == 0);
- g_free(data);
+ HugeFree(data, CalcAllocationSize());
}
SliceBuffer(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 {
return n_max;
}
@@ -136,6 +147,14 @@ public:
slice->next = available;
available = slice;
--n_allocated;
+
+ /* give memory back to the kernel when the last slice
+ was freed */
+ if (n_allocated == 0) {
+ HugeDiscard(data, CalcAllocationSize());
+ n_initialized = 0;
+ available = nullptr;
+ }
}
};