mirror of
https://github.com/SFML/SFML.git
synced 2024-12-01 15:51:04 +08:00
Fix autorelease problem (issue #62)
This commit is contained in:
parent
de70f691e1
commit
edf82be16b
@ -74,6 +74,8 @@ else() # MACOSX
|
||||
${SRCROOT}/OSX/WindowImplCocoa.hpp
|
||||
${SRCROOT}/OSX/WindowImplCocoa.mm
|
||||
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
|
28
src/SFML/Window/OSX/AutoreleasePoolWrapper.h
Normal file
28
src/SFML/Window/OSX/AutoreleasePoolWrapper.h
Normal file
@ -0,0 +1,28 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void RetainPool(void);
|
||||
void ReleasePool(void);
|
||||
|
138
src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
Normal file
138
src/SFML/Window/OSX/AutoreleasePoolWrapper.mm
Normal file
@ -0,0 +1,138 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
|
||||
// Laurent Gomila (laurent.gom@gmail.com),
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#import "AutoreleasePoolWrapper.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Here we manage one and only one pool by thread. This prevents draining one
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
|
||||
class PoolWrapper {
|
||||
public:
|
||||
PoolWrapper()
|
||||
: count(0)
|
||||
, pool(0)
|
||||
{
|
||||
/* Nothing else */
|
||||
}
|
||||
|
||||
~PoolWrapper()
|
||||
{
|
||||
#ifdef SFML_DEBUG
|
||||
if (count < 0) {
|
||||
sf::Err() << "~PoolWrapper : count is less than zero! "
|
||||
"You called ReleasePool from a thread too many times."
|
||||
<< std::endl;
|
||||
} else if (count > 0) {
|
||||
sf::Err() << "~PoolWrapper : count is greater than zero! "
|
||||
"You called ReleasePool from a thread to few times."
|
||||
<< std::endl;
|
||||
} else { // count == 0
|
||||
sf::Err() << "~PoolWrapper is HAPPY!" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Retain()
|
||||
{
|
||||
// Increase counter.
|
||||
++count;
|
||||
|
||||
// Allocate pool if required.
|
||||
if (pool == 0) {
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
#ifdef SFML_DEBUG
|
||||
if (count <= 0) {
|
||||
sf::Err() << "PoolWrapper::Retain : count <= 0! " << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
// Decrease counter.
|
||||
--count;
|
||||
|
||||
// Drain pool if required.
|
||||
if (count == 0) {
|
||||
[pool drain];
|
||||
pool = 0;
|
||||
}
|
||||
|
||||
#ifdef SFML_DEBUG
|
||||
if (count < 0) {
|
||||
sf::Err() << "PoolWrapper::Release : count < 0! " << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int count; ///< How many times the pool was retained ?
|
||||
NSAutoreleasePool* pool; ///< Our pool.
|
||||
};
|
||||
|
||||
// Thread shared variable but with local-only shared content.
|
||||
sf::ThreadLocalPtr<PoolWrapper> localPool;
|
||||
|
||||
void RetainPool(void)
|
||||
{
|
||||
// First, Check that we have a valid PoolWrapper object in our local pool.
|
||||
if (localPool == NULL) {
|
||||
localPool = new PoolWrapper();
|
||||
}
|
||||
|
||||
// Then retains!
|
||||
localPool->Retain();
|
||||
}
|
||||
|
||||
void ReleasePool(void)
|
||||
{
|
||||
#ifdef SFML_DEBUG
|
||||
if (localPool == NULL) {
|
||||
sf::Err() << "ReleasePool : You must call RetainPool at least once "
|
||||
"in this thread before calling ReleasePool."
|
||||
<< std::endl;
|
||||
} else {
|
||||
#endif
|
||||
|
||||
// Releases, that's all.
|
||||
localPool->Release();
|
||||
|
||||
#ifdef SFML_DEBUG
|
||||
}
|
||||
#endif
|
||||
}
|
@ -39,9 +39,6 @@
|
||||
@class NSOpenGLContext;
|
||||
typedef NSOpenGLContext* NSOpenGLContextRef;
|
||||
|
||||
@class NSAutoreleasePool;
|
||||
typedef NSAutoreleasePool* NSAutoreleasePoolRef;
|
||||
|
||||
@class NSOpenGLView;
|
||||
typedef NSOpenGLView* NSOpenGLViewRef;
|
||||
|
||||
@ -51,7 +48,6 @@ typedef NSWindow* NSWindowRef;
|
||||
#else // If C++
|
||||
|
||||
typedef void* NSOpenGLContextRef;
|
||||
typedef void* NSAutoreleasePoolRef;
|
||||
typedef void* NSOpenGLViewRef;
|
||||
typedef void* NSWindowRef;
|
||||
|
||||
@ -154,7 +150,6 @@ private:
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
NSOpenGLContextRef myContext; ///< OpenGL context.
|
||||
NSAutoreleasePoolRef myPool; ///< Memory manager for this class.
|
||||
NSOpenGLViewRef myView; ///< Only for offscreen context.
|
||||
NSWindowRef myWindow; ///< Only for offscreen context.
|
||||
};
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||
|
||||
/*
|
||||
* DISCUSSION :
|
||||
* ============
|
||||
@ -53,7 +55,8 @@ namespace priv
|
||||
SFContext::SFContext(SFContext* shared)
|
||||
: myView(0), myWindow(0)
|
||||
{
|
||||
myPool = [[NSAutoreleasePool alloc] init];
|
||||
// Ask for a pool.
|
||||
RetainPool();
|
||||
|
||||
// Create the context
|
||||
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
|
||||
@ -65,7 +68,8 @@ SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
|
||||
const WindowImpl* owner, unsigned int bitsPerPixel)
|
||||
: myView(0), myWindow(0)
|
||||
{
|
||||
myPool = [[NSAutoreleasePool alloc] init];
|
||||
// Ask for a pool.
|
||||
RetainPool();
|
||||
|
||||
// Create the context.
|
||||
CreateContext(shared, bitsPerPixel, settings);
|
||||
@ -83,7 +87,8 @@ SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
|
||||
// Ensure the process is setup in order to create a valid window.
|
||||
WindowImplCocoa::SetUpProcess();
|
||||
|
||||
myPool = [[NSAutoreleasePool alloc] init];
|
||||
// Ask for a pool.
|
||||
RetainPool();
|
||||
|
||||
// Create the context.
|
||||
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, settings);
|
||||
@ -109,8 +114,7 @@ SFContext::~SFContext()
|
||||
[myView release]; // Might be nil but we don't care.
|
||||
[myWindow release]; // Idem.
|
||||
|
||||
[myPool drain]; // Produce sometimes "*** attempt to pop an unknown autorelease pool"
|
||||
// This is not a real issue : http://stackoverflow.com/questions/3484888/nsautoreleasepool-question
|
||||
ReleasePool();
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,9 +40,6 @@
|
||||
#import <SFML/Window/OSX/WindowImplDelegateProtocol.h>
|
||||
typedef id<WindowImplDelegateProtocol,NSObject> WindowImplDelegateRef;
|
||||
|
||||
@class NSAutoreleasePool;
|
||||
typedef NSAutoreleasePool* NSAutoreleasePoolRef;
|
||||
|
||||
@class NSOpenGLContext;
|
||||
typedef NSOpenGLContext* NSOpenGLContextRef;
|
||||
|
||||
@ -51,7 +48,6 @@ typedef NSOpenGLContext* NSOpenGLContextRef;
|
||||
typedef unsigned short unichar; // See NSString.h
|
||||
|
||||
typedef void* WindowImplDelegateRef;
|
||||
typedef void* NSAutoreleasePoolRef;
|
||||
typedef void* NSOpenGLContextRef;
|
||||
|
||||
#endif
|
||||
@ -326,7 +322,6 @@ private:
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
WindowImplDelegateRef myDelegate; ///< Implementation in Obj-C.
|
||||
NSAutoreleasePoolRef myPool; ///< Memory manager for this class.
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
@ -32,6 +32,7 @@
|
||||
#import <SFML/Window/OSX/SFWindowController.h>
|
||||
#import <SFML/Window/OSX/SFViewController.h>
|
||||
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
||||
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -44,8 +45,8 @@ namespace priv
|
||||
////////////////////////////////////////////////////////////
|
||||
WindowImplCocoa::WindowImplCocoa(WindowHandle handle)
|
||||
{
|
||||
// Create the pool.
|
||||
myPool = [[NSAutoreleasePool alloc] init];
|
||||
// Ask for a pool.
|
||||
RetainPool();
|
||||
|
||||
// Treat the handle as it real type
|
||||
id nsHandle = (id)handle;
|
||||
@ -94,8 +95,8 @@ WindowImplCocoa::WindowImplCocoa(VideoMode mode,
|
||||
// Transform the app process.
|
||||
SetUpProcess();
|
||||
|
||||
// Create the pool.
|
||||
myPool = [[NSAutoreleasePool alloc] init];
|
||||
// Ask for a pool.
|
||||
RetainPool();
|
||||
|
||||
// Don't forget to update our parent (that is, WindowImpl) size :
|
||||
myWidth = mode.Width;
|
||||
@ -113,7 +114,8 @@ WindowImplCocoa::~WindowImplCocoa()
|
||||
[myDelegate closeWindow];
|
||||
|
||||
[myDelegate release];
|
||||
[myPool drain];
|
||||
|
||||
ReleasePool();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user