From b19f4b551ee6ea0d74e29af6c219788b65fc2ecd Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 10 Apr 2018 06:16:37 +0200 Subject: fix memory management issues --- src/adlmidi_opl3.cpp | 2 +- src/adlmidi_private.hpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index 7fc7f4e..308e380 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -521,7 +521,7 @@ void OPL3::Reset(int emulator, unsigned long PCM_RATE) regBD.clear(); #ifndef ADLMIDI_HW_OPL - cardsOP2.resize(NumCards, AdlMIDI_CPtr()); + cardsOP2.resize(NumCards, AdlMIDI_SPtr()); #endif NumChannels = NumCards * 23; diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 4f727e2..395b7f7 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -143,9 +143,11 @@ public: void reset(PTR *p = NULL) { - if(m_p) - free(m_p); - m_p = p; + if(p != m_p) { + if(m_p) + free(m_p); + m_p = p; + } } PTR *get() @@ -160,6 +162,77 @@ public: { return m_p; } +private: + AdlMIDI_CPtr(const AdlMIDI_CPtr &); + AdlMIDI_CPtr &operator=(const AdlMIDI_CPtr &); +}; + +/* + Shared pointer with non-atomic counter + FAQ: Why not std::shared_ptr? Because of Android NDK now doesn't supports it +*/ +template +class AdlMIDI_SPtr +{ + VALUE *m_p; + size_t *m_counter; +public: + AdlMIDI_SPtr() : m_p(NULL), m_counter(NULL) {} + ~AdlMIDI_SPtr() + { + reset(NULL); + } + + AdlMIDI_SPtr(const AdlMIDI_SPtr &other) + : m_p(other.m_p), m_counter(other.m_counter) + { + if(m_counter) + ++*m_counter; + } + + AdlMIDI_SPtr &operator=(const AdlMIDI_SPtr &other) + { + reset(); + m_p = other.m_p; + m_counter = other.m_counter; + if(m_counter) + ++*m_counter; + return *this; + } + + void reset(VALUE *p = NULL) + { + if(p != m_p) { + if(m_p && --*m_counter == 0) + delete m_p; + m_p = p; + if(!p) { + if(m_counter) { + delete m_counter; + m_counter = NULL; + } + } + else + { + if(!m_counter) + m_counter = new size_t; + *m_counter = 1; + } + } + } + + VALUE *get() + { + return m_p; + } + VALUE &operator*() + { + return *m_p; + } + VALUE *operator->() + { + return m_p; + } }; class MIDIplay; @@ -173,7 +246,7 @@ public: char ____padding[4]; ADL_MIDIPlayer *_parent; #ifndef ADLMIDI_HW_OPL - std::vector > cardsOP2; + std::vector > cardsOP2; #endif private: std::vector ins; // index to adl[], cached, needed by Touch() -- cgit v1.2.3