diff options
Diffstat (limited to 'src/SFML/Window/OSX/AutoreleasePoolWrapper.mm')
-rw-r--r-- | src/SFML/Window/OSX/AutoreleasePoolWrapper.mm | 168 |
1 files changed, 34 insertions, 134 deletions
diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm index 2afd8ab..f0ae7b4 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2015 Marco Antognini (antognini.marco@gmail.com), +// Copyright (C) 2007-2016 Marco Antognini (antognini.marco@gmail.com), // Laurent Gomila (laurent@sfml-dev.org) // // This software is provided 'as-is', without any express or implied warranty. @@ -26,11 +26,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include <SFML/System/Err.hpp> -#include <SFML/System/NonCopyable.hpp> -#include <SFML/System/ThreadLocalPtr.hpp> - #include <cassert> +#include <pthread.h> #import <SFML/Window/OSX/AutoreleasePoolWrapper.h> #import <Foundation/Foundation.h> @@ -41,165 +38,68 @@ /// pool and making other pools invalid which can lead to a crash on 10.5 and an /// annoying message on 10.6 (*** attempt to pop an unknown autorelease pool). /// -/// Because NSAutoreleasePool cannot be retain we have to do it ourself. -/// We use an sf::ThreadLocalPtr to have one PoolWrapper in each thread. -/// -/// SPECIAL CONSIDERATION: -/// ====================== -/// This implies that if retainPool is called X times in a thread Y then -/// releasePool must be called X times too in the same thread Y. -/// //////////////////////////////////////////////////////////// -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief C++ Wrapper of Obj-C Autorelease Pool -/// -//////////////////////////////////////////////////////////// -class PoolWrapper : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - PoolWrapper(); - - //////////////////////////////////////////////////////////// - /// \brief Default destructor - /// - /// Make sure the pool is drained (if appropriate) - /// - //////////////////////////////////////////////////////////// - ~PoolWrapper(); - - //////////////////////////////////////////////////////////// - /// \brief Increment retain count and allocate memory if needed - /// - //////////////////////////////////////////////////////////// - void retain(); - - //////////////////////////////////////////////////////////// - /// \brief Decrement retain count and releasing memory if needed - /// - /// \return true if the pool wrapper can be released - /// - //////////////////////////////////////////////////////////// - bool release(); - - //////////////////////////////////////////////////////////// - /// \brief Drain the pool - /// - //////////////////////////////////////////////////////////// - void drain(); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - int m_count; ///< How many times was the pool retained? - NSAutoreleasePool* m_pool; ///< Our dedicated pool -}; - - -//////////////////////////////////////////////////////////// -PoolWrapper::PoolWrapper() : -m_count(0), -m_pool(nil) -{ - /* Nothing else */ -} - //////////////////////////////////////////////////////////// -PoolWrapper::~PoolWrapper() -{ - // Make sure everything is drained - m_count = 0; - drain(); -} - - +// Private data //////////////////////////////////////////////////////////// -void PoolWrapper::retain() -{ - // Increase counter - ++m_count; - - // Allocate pool if required - if (m_pool == nil) - m_pool = [[NSAutoreleasePool alloc] init]; -} +static pthread_key_t poolKey; +static pthread_once_t initOnceToken = PTHREAD_ONCE_INIT; //////////////////////////////////////////////////////////// -bool PoolWrapper::release() -{ - // Decrease counter - --m_count; - - return m_count == 0; -} - -void PoolWrapper::drain() +/// \brief (local function) Drain one more time the pool +/// but this time don't create a new one. +/// +//////////////////////////////////////////////////////////// +static void destroyPool(void* data) { - [m_pool drain]; - m_pool = nil; - - if (m_count != 0) - m_pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = (NSAutoreleasePool*)data; + [pool drain]; } -} // namespace priv - -} // namespace sf - //////////////////////////////////////////////////////////// -// Private data +/// \brief (local function) Init the pthread key for the pool +/// //////////////////////////////////////////////////////////// -namespace +static void createPoolKey(void) { - // This per-thread variable holds the current autorelease pool for each thread - sf::ThreadLocalPtr<sf::priv::PoolWrapper> localPool; + pthread_key_create(&poolKey, destroyPool); } //////////////////////////////////////////////////////////// -void retainPool(void) +/// \brief (local function) Store a new pool for this thread +/// +//////////////////////////////////////////////////////////// +static void createNewPool(void) { - // First, Check that we have a valid PoolWrapper object in our local pool. - if (localPool == NULL) - localPool = new sf::priv::PoolWrapper(); - - // Then retains! - localPool->retain(); + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + pthread_setspecific(poolKey, pool); } //////////////////////////////////////////////////////////// -void drainCurrentPool(void) +void ensureThreadHasPool(void) { - assert(localPool != NULL); - localPool->drain(); + pthread_once(&initOnceToken, createPoolKey); + if (pthread_getspecific(poolKey) == NULL) + { + createNewPool(); + } } //////////////////////////////////////////////////////////// -void releasePool(void) +void drainThreadPool(void) { - assert(localPool != NULL); + void* data = pthread_getspecific(poolKey); + assert(data != NULL); - // If we're done with the pool, let's release the memory - if (localPool->release()) - { - delete localPool; - localPool = NULL; - } + // Drain the pool but keep it alive by creating a new one + destroyPool(data); + createNewPool(); } |