Index: intern/audaspace/intern/AUD_Reference.h =================================================================== --- intern/audaspace/intern/AUD_Reference.h (revisão 46420) +++ intern/audaspace/intern/AUD_Reference.h (cópia de trabalho) @@ -31,81 +31,30 @@ #include #include -#include +#include -// #define MEM_DEBUG - -#ifdef MEM_DEBUG -#include -#include -#endif - /** - * This class handles the reference counting. - */ -class AUD_ReferenceHandler -{ -private: - /** - * Saves the reference counts. - */ - static std::map m_references; - static pthread_mutex_t m_mutex; - static bool m_mutex_initialised; - -public: - - static pthread_mutex_t* getMutex(); - - /** - * Reference increment. - * \param reference The reference. - */ - static inline void incref(void* reference) - { - if(!reference) - return; - - std::map::iterator result = m_references.find(reference); - if(result != m_references.end()) - { - m_references[reference]++; - } - else - { - m_references[reference] = 1; - } - } - - /** - * Reference decrement. - * \param reference The reference. - * \return Whether the reference has to be deleted. - */ - static inline bool decref(void* reference) - { - if(!reference) - return false; - - if(!--m_references[reference]) - { - m_references.erase(reference); - return true; - } - return false; - } -}; - -template -/** * This class provides reference counting functionality. + * + * Important: + * + * AUD_Reference used to have a global reference count table, + * which caused the following code be valid: + * + * class A {}; + * + * A *pa = new A(); + * AUD_Reference r1(a); + * AUD_Reference r2(a); + * + * Now with the new implementation using boost:shared_ptr, the + * above code will result in a double delete, so it is no longer + * valid. Existing code must be revised to check against this + * situation. */ +template class AUD_Reference { -private: - /// The reference. - T* m_reference; - void* m_original; public: /** * Creates a new reference counter. @@ -113,22 +62,12 @@ */ template AUD_Reference(U* reference) + : m_reference(reference) { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = reference; - m_reference = dynamic_cast(reference); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); } AUD_Reference() { - m_original = NULL; - m_reference = NULL; } /** @@ -136,95 +75,22 @@ * \param ref The AUD_Reference object to copy. */ AUD_Reference(const AUD_Reference& ref) + : m_reference(ref.m_reference) { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); } template explicit AUD_Reference(const AUD_Reference& ref) + : m_reference(boost::dynamic_pointer_cast(ref.m_reference)) { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.get(); - m_reference = dynamic_cast(ref.get()); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); } /** - * Destroys a AUD_Reference object, if there's no furthere reference on the - * reference, it is destroyed as well. - */ - ~AUD_Reference() - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - } - else - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - } - - /** - * Assigns an AUD_Reference to this object. - * \param ref The AUD_Reference object to assign. - */ - AUD_Reference& operator=(const AUD_Reference& ref) - { - if(&ref == this) - return *this; - - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - } - - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - - return *this; - } - - /** * Returns whether the reference is NULL. */ inline bool isNull() const { - return m_reference == NULL; + return !m_reference; } /** @@ -232,18 +98,10 @@ */ inline T* get() const { - return m_reference; + return m_reference.get(); } /** - * Returns the original pointer. - */ - inline void* getOriginal() const - { - return m_original; - } - - /** * Returns the reference. */ inline T& operator*() const @@ -256,20 +114,27 @@ */ inline T* operator->() const { - return m_reference; + return get(); } + +private: + template friend class AUD_Reference; + template friend bool operator==(const AUD_Reference &a, const AUD_Reference &b); + template friend bool operator!=(const AUD_Reference &a, const AUD_Reference &b); + + boost::shared_ptr m_reference; }; template inline bool operator==(const AUD_Reference& a, const AUD_Reference& b) { - return a.getOriginal() == b.getOriginal(); + return a.m_reference == b.m_reference; } template inline bool operator!=(const AUD_Reference& a, const AUD_Reference& b) { - return a.getOriginal() != b.getOriginal(); + return a.m_reference != b.m_reference; } #endif // __AUD_REFERENCE_H__ Index: intern/audaspace/intern/AUD_ReferenceHandler.cpp =================================================================== --- intern/audaspace/intern/AUD_ReferenceHandler.cpp (revisão 46420) +++ intern/audaspace/intern/AUD_ReferenceHandler.cpp (cópia de trabalho) @@ -28,25 +28,5 @@ #include "AUD_Reference.h" -std::map AUD_ReferenceHandler::m_references; -pthread_mutex_t AUD_ReferenceHandler::m_mutex; -bool AUD_ReferenceHandler::m_mutex_initialised = false; -pthread_mutex_t *AUD_ReferenceHandler::getMutex() -{ - if(!m_mutex_initialised) - { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); - - m_mutex_initialised = true; - } - - return &m_mutex; -} - Index: intern/audaspace/OpenAL/AUD_OpenALDevice.cpp =================================================================== --- intern/audaspace/OpenAL/AUD_OpenALDevice.cpp (revisão 46420) +++ intern/audaspace/OpenAL/AUD_OpenALDevice.cpp (cópia de trabalho) @@ -41,6 +41,10 @@ #include #endif +#include +#include +#include + /*struct AUD_OpenALBufferedFactory { /// The factory. @@ -52,7 +56,6 @@ //typedef std::list::iterator AUD_BFIterator; - /******************************************************************************/ /*********************** AUD_OpenALHandle Handle Code *************************/ /******************************************************************************/ @@ -169,6 +172,25 @@ return false; } +template +InputIterator AUD_OpenALDevice::AUD_OpenALHandle::findSound(InputIterator first, InputIterator end) +{ + using boost::bind; + + typedef AUD_Reference reference_type; + + /* + * As the handle's are stored wrapped by an AUD_Reference object and we have + * only the raw pointer, we have to manually do a linear search in the container + * comparing the pointers. + */ + return std::find_if(first, + end, + // element.get() == this + bind(std::equal_to(), + bind(&reference_type::get, _1), this)); +} + bool AUD_OpenALDevice::AUD_OpenALHandle::stop() { if(!m_status) @@ -178,12 +200,22 @@ // AUD_XXX Create a reference of our own object so that it doesn't get // deleted before the end of this function - AUD_Reference This = this; + AUD_Reference This; if(m_status == AUD_STATUS_PLAYING) - m_device->m_playingSounds.remove(This); + { + AUD_HandleIterator it = findSound(m_device->m_playingSounds.begin(), + m_device->m_playingSounds.end()); + This = *it; + m_device->m_playingSounds.erase(it); + } else - m_device->m_pausedSounds.remove(This); + { + AUD_HandleIterator it = findSound(m_device->m_pausedSounds.begin(), + m_device->m_pausedSounds.end()); + This = *it; + m_device->m_pausedSounds.erase(it); + } m_device->unlock(); Index: intern/audaspace/OpenAL/AUD_OpenALDevice.h =================================================================== --- intern/audaspace/OpenAL/AUD_OpenALDevice.h (revisão 46420) +++ intern/audaspace/OpenAL/AUD_OpenALDevice.h (cópia de trabalho) @@ -148,6 +148,12 @@ virtual bool setConeAngleInner(float angle); virtual float getConeVolumeOuter(); virtual bool setConeVolumeOuter(float volume); + + private: + + // only used in the implementation module, no need to be defined in the header file + template + InputIterator findSound(InputIterator first, InputIterator end); }; typedef std::list >::iterator AUD_HandleIterator;