Commit 223b90d0 authored by Max Kellermann's avatar Max Kellermann

MusicBuffer: return memory to kernel when stopping playback

Use the new HugeAllocator as backend for SliceBuffer and call HugeDiscard() when the last chunk was returned.
parent 692b2cfb
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "MusicBuffer.hxx" #include "MusicBuffer.hxx"
#include "MusicChunk.hxx" #include "MusicChunk.hxx"
#include "util/SliceBuffer.hxx" #include "util/SliceBuffer.hxx"
#include "mpd_error.h"
#include <glib.h> #include <glib.h>
...@@ -32,7 +33,10 @@ struct music_buffer : public SliceBuffer<music_chunk> { ...@@ -32,7 +33,10 @@ struct music_buffer : public SliceBuffer<music_chunk> {
music_buffer(unsigned num_chunks) music_buffer(unsigned num_chunks)
:SliceBuffer(num_chunks), :SliceBuffer(num_chunks),
mutex(g_mutex_new()) {} mutex(g_mutex_new()) {
if (IsOOM())
MPD_ERROR("Failed to allocate buffer");
}
~music_buffer() { ~music_buffer() {
g_mutex_free(mutex); g_mutex_free(mutex);
......
...@@ -20,10 +20,9 @@ ...@@ -20,10 +20,9 @@
#ifndef MPD_SLICE_BUFFER_HXX #ifndef MPD_SLICE_BUFFER_HXX
#define MPD_SLICE_BUFFER_HXX #define MPD_SLICE_BUFFER_HXX
#include "HugeAllocator.hxx"
#include "gcc.h" #include "gcc.h"
#include <glib.h>
#include <utility> #include <utility>
#include <new> #include <new>
...@@ -66,10 +65,15 @@ class SliceBuffer { ...@@ -66,10 +65,15 @@ class SliceBuffer {
*/ */
Slice *available; Slice *available;
size_t CalcAllocationSize() const {
return n_max * sizeof(Slice);
}
public: public:
SliceBuffer(unsigned _count) SliceBuffer(unsigned _count)
:n_max(_count), n_initialized(0), n_allocated(0), :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); assert(n_max > 0);
} }
...@@ -78,12 +82,19 @@ public: ...@@ -78,12 +82,19 @@ public:
assertion checks for leaks */ assertion checks for leaks */
assert(n_allocated == 0); assert(n_allocated == 0);
g_free(data); HugeFree(data, CalcAllocationSize());
} }
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;
} }
...@@ -136,6 +147,14 @@ public: ...@@ -136,6 +147,14 @@ public:
slice->next = available; slice->next = available;
available = slice; available = slice;
--n_allocated; --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;
}
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment