From 7f8a69d6fc44ca5515a91f29ce5451c12f85daa5 Mon Sep 17 00:00:00 2001 From: athrxx Date: Sun, 29 May 2011 21:43:38 +0200 Subject: FM-TOWNS AUDIO: fix destructors (thread safety) --- audio/softsynth/fmtowns_pc98/towns_audio.cpp | 73 +++++++++++++--------- audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 2 + .../softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 8 ++- audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 8 +-- 4 files changed, 57 insertions(+), 34 deletions(-) (limited to 'audio/softsynth') diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 42a8252d53..efc9f9fb62 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -103,12 +103,11 @@ private: class TownsAudioInterfaceInternal : public TownsPC98_FmSynth { public: - TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); ~TownsAudioInterfaceInternal(); - static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); - static void releaseRef(); - bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + static void releaseRef(TownsAudioInterface *owner); bool init(); @@ -122,6 +121,9 @@ public: void setSoundEffectChanMask(int mask); private: + bool assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false); + void removePluginDriver(TownsAudioInterface *owner); + void nextTickEx(int32 *buffer, uint32 bufferSize); void timerCallbackA(); @@ -239,6 +241,7 @@ private: int _pcmSfxChanMask; TownsAudioInterfacePluginDriver *_drv; + void *_drvOwner; bool _ready; static TownsAudioInterfaceInternal *_refInstance; @@ -252,10 +255,10 @@ private: static const uint16 _pcmPhase2[]; }; -TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) : +TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) : TownsPC98_FmSynth(mixer, kTypeTowns, externalMutexHandling), _fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0), - _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), + _baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver), _drvOwner(owner), _pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume), _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0), _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0), @@ -388,6 +391,8 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { _ready = false; deinit(); + Common::StackLock lock(_mutex); + delete[] _fmSaveReg[0]; delete[] _fmSaveReg[1]; delete[] _fmInstruments; @@ -396,45 +401,33 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() { delete[] _pcmChan; } -TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { _refCount++; if (_refCount == 1 && _refInstance == 0) - _refInstance = new TownsAudioInterfaceInternal(mixer, driver, externalMutexHandling); + _refInstance = new TownsAudioInterfaceInternal(mixer, owner, driver, externalMutexHandling); else if (_refCount < 2 || _refInstance == 0) error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure"); - else if (!_refInstance->checkPluginDriver(driver, externalMutexHandling)) + else if (!_refInstance->assignPluginDriver(owner, driver, externalMutexHandling)) error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict"); return _refInstance; } -void TownsAudioInterfaceInternal::releaseRef() { +void TownsAudioInterfaceInternal::releaseRef(TownsAudioInterface *owner) { if (!_refCount) return; _refCount--; - if (!_refCount) { + if (_refCount) { + if (_refInstance) + _refInstance->removePluginDriver(owner); + } else { delete _refInstance; _refInstance = 0; } } -bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { - if (_refCount <= 1) - return true; - - if (_drv) { - if (driver && driver != _drv) - return false; - } else { - _drv = driver; - _externalMutex = externalMutexHandling; - } - - return true; -} - bool TownsAudioInterfaceInternal::init() { if (_ready) return true; @@ -501,6 +494,30 @@ void TownsAudioInterfaceInternal::setSoundEffectChanMask(int mask) { setVolumeChannelMasks(~mask, mask); } +bool TownsAudioInterfaceInternal::assignPluginDriver(TownsAudioInterface *owner, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { + if (_refCount <= 1) + return true; + + if (_drv) { + if (driver && driver != _drv) + return false; + } else { + Common::StackLock lock(_mutex); + _drv = driver; + _drvOwner = owner; + _externalMutex = externalMutexHandling; + } + + return true; +} + +void TownsAudioInterfaceInternal::removePluginDriver(TownsAudioInterface *owner) { + if (_drvOwner == owner) { + Common::StackLock lock(_mutex); + _drv = 0; + } +} + void TownsAudioInterfaceInternal::nextTickEx(int32 *buffer, uint32 bufferSize) { if (!_ready) return; @@ -1856,11 +1873,11 @@ void TownsAudio_WaveTable::clear() { } TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) { - _intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver, externalMutexHandling); + _intf = TownsAudioInterfaceInternal::addNewRef(mixer, this, driver, externalMutexHandling); } TownsAudioInterface::~TownsAudioInterface() { - TownsAudioInterfaceInternal::releaseRef(); + TownsAudioInterfaceInternal::releaseRef(this); _intf = 0; } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index ee20068e74..49fe97caf1 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -1054,6 +1054,8 @@ TownsPC98_AudioDriver::~TownsPC98_AudioDriver() { _ready = false; deinit(); + Common::StackLock lock(_mutex); + if (_channels) { for (int i = 0; i < _numChan; i++) delete _channels[i]; diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index f4dd3cf6cc..63007ba93c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -875,6 +875,8 @@ TownsPC98_FmSynth::~TownsPC98_FmSynth() { if (_ready) deinit(); + Common::StackLock lock(_mutex); + delete _ssg; #ifndef DISABLE_PC98_RHYTHM_CHANNEL delete _prc; @@ -1166,7 +1168,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { (this->*_timers[i].cb)(); - if (_ready && !locked && _externalMutex) { + if (!locked && _externalMutex) { _mutex.lock(); locked = true; } @@ -1240,6 +1242,10 @@ void TownsPC98_FmSynth::deinit() { _timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback; } +void TownsPC98_FmSynth::toggleRegProtection(bool prot) { + _regProtectionFlag = prot; +} + uint8 TownsPC98_FmSynth::readSSGStatus() { return _ssg->chanEnable(); } diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index 50a05f92a9..4f81fa9a5c 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -80,17 +80,15 @@ protected: // additional output that has to be inserted into the buffer. virtual void nextTickEx(int32 *buffer, uint32 bufferSize) {} - void toggleRegProtection(bool prot) { - _regProtectionFlag = prot; - } + void toggleRegProtection(bool prot); uint8 readSSGStatus(); virtual void timerCallbackA() = 0; virtual void timerCallbackB() = 0; - // The audio driver can store and apply two different audio settings + // The audio driver can store and apply two different volume settings // (usually for music and sound effects). The channel mask will determine - // which channels get effected by the setting. The first bits will be + // which channels get effected by which setting. The first bits will be // the normal fm channels, the next bits the ssg channels and the final // bit the rhythm channel. void setVolumeIntern(int volA, int volB); -- cgit v1.2.3