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.
This commit is contained in:
@@ -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> {
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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 {
|
|||||||
*/
|
*/
|
||||||
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:
|
|||||||
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:
|
|||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user