diff options
author | Vitaly Novichkov <Wohlstand@users.noreply.github.com> | 2018-04-10 10:32:57 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-10 10:32:57 +0300 |
commit | 7ee2255ba11cad215a255a709795443e731679d3 (patch) | |
tree | 03441e9a6cf8720a9b6227aa7f86a8fff0dc6515 /src | |
parent | cd09e3835c59ffdaeec9666d0ee0cddea98772bf (diff) | |
parent | b19f4b551ee6ea0d74e29af6c219788b65fc2ecd (diff) | |
download | libADLMIDI-7ee2255ba11cad215a255a709795443e731679d3.tar.gz libADLMIDI-7ee2255ba11cad215a255a709795443e731679d3.tar.bz2 libADLMIDI-7ee2255ba11cad215a255a709795443e731679d3.zip |
Merge pull request #52 from jpcima/fix-memory-problems
fix memory management issues
Diffstat (limited to 'src')
-rw-r--r-- | src/adlmidi_opl3.cpp | 2 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 81 |
2 files changed, 78 insertions, 5 deletions
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<OPLChipBase>()); + cardsOP2.resize(NumCards, AdlMIDI_SPtr<OPLChipBase>()); #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 VALUE> +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<AdlMIDI_CPtr<OPLChipBase > > cardsOP2; + std::vector<AdlMIDI_SPtr<OPLChipBase > > cardsOP2; #endif private: std::vector<size_t> ins; // index to adl[], cached, needed by Touch() |