summaryrefslogtreecommitdiff
path: root/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Window/OSX/AutoreleasePoolWrapper.mm')
-rw-r--r--src/SFML/Window/OSX/AutoreleasePoolWrapper.mm168
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();
}