mirror of
https://github.com/SFML/SFML.git
synced 2024-12-03 08:41: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.hpp
|
||||||
${SRCROOT}/OSX/WindowImplCocoa.mm
|
${SRCROOT}/OSX/WindowImplCocoa.mm
|
||||||
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
|
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
|
||||||
|
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
|
||||||
|
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
|
||||||
)
|
)
|
||||||
endif()
|
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;
|
@class NSOpenGLContext;
|
||||||
typedef NSOpenGLContext* NSOpenGLContextRef;
|
typedef NSOpenGLContext* NSOpenGLContextRef;
|
||||||
|
|
||||||
@class NSAutoreleasePool;
|
|
||||||
typedef NSAutoreleasePool* NSAutoreleasePoolRef;
|
|
||||||
|
|
||||||
@class NSOpenGLView;
|
@class NSOpenGLView;
|
||||||
typedef NSOpenGLView* NSOpenGLViewRef;
|
typedef NSOpenGLView* NSOpenGLViewRef;
|
||||||
|
|
||||||
@ -51,7 +48,6 @@ typedef NSWindow* NSWindowRef;
|
|||||||
#else // If C++
|
#else // If C++
|
||||||
|
|
||||||
typedef void* NSOpenGLContextRef;
|
typedef void* NSOpenGLContextRef;
|
||||||
typedef void* NSAutoreleasePoolRef;
|
|
||||||
typedef void* NSOpenGLViewRef;
|
typedef void* NSOpenGLViewRef;
|
||||||
typedef void* NSWindowRef;
|
typedef void* NSWindowRef;
|
||||||
|
|
||||||
@ -154,7 +150,6 @@ private:
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
NSOpenGLContextRef myContext; ///< OpenGL context.
|
NSOpenGLContextRef myContext; ///< OpenGL context.
|
||||||
NSAutoreleasePoolRef myPool; ///< Memory manager for this class.
|
|
||||||
NSOpenGLViewRef myView; ///< Only for offscreen context.
|
NSOpenGLViewRef myView; ///< Only for offscreen context.
|
||||||
NSWindowRef myWindow; ///< Only for offscreen context.
|
NSWindowRef myWindow; ///< Only for offscreen context.
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
|
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DISCUSSION :
|
* DISCUSSION :
|
||||||
* ============
|
* ============
|
||||||
@ -53,7 +55,8 @@ namespace priv
|
|||||||
SFContext::SFContext(SFContext* shared)
|
SFContext::SFContext(SFContext* shared)
|
||||||
: myView(0), myWindow(0)
|
: myView(0), myWindow(0)
|
||||||
{
|
{
|
||||||
myPool = [[NSAutoreleasePool alloc] init];
|
// Ask for a pool.
|
||||||
|
RetainPool();
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
|
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)
|
const WindowImpl* owner, unsigned int bitsPerPixel)
|
||||||
: myView(0), myWindow(0)
|
: myView(0), myWindow(0)
|
||||||
{
|
{
|
||||||
myPool = [[NSAutoreleasePool alloc] init];
|
// Ask for a pool.
|
||||||
|
RetainPool();
|
||||||
|
|
||||||
// Create the context.
|
// Create the context.
|
||||||
CreateContext(shared, bitsPerPixel, settings);
|
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.
|
// Ensure the process is setup in order to create a valid window.
|
||||||
WindowImplCocoa::SetUpProcess();
|
WindowImplCocoa::SetUpProcess();
|
||||||
|
|
||||||
myPool = [[NSAutoreleasePool alloc] init];
|
// Ask for a pool.
|
||||||
|
RetainPool();
|
||||||
|
|
||||||
// Create the context.
|
// Create the context.
|
||||||
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, settings);
|
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, settings);
|
||||||
@ -109,8 +114,7 @@ SFContext::~SFContext()
|
|||||||
[myView release]; // Might be nil but we don't care.
|
[myView release]; // Might be nil but we don't care.
|
||||||
[myWindow release]; // Idem.
|
[myWindow release]; // Idem.
|
||||||
|
|
||||||
[myPool drain]; // Produce sometimes "*** attempt to pop an unknown autorelease pool"
|
ReleasePool();
|
||||||
// This is not a real issue : http://stackoverflow.com/questions/3484888/nsautoreleasepool-question
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,9 +40,6 @@
|
|||||||
#import <SFML/Window/OSX/WindowImplDelegateProtocol.h>
|
#import <SFML/Window/OSX/WindowImplDelegateProtocol.h>
|
||||||
typedef id<WindowImplDelegateProtocol,NSObject> WindowImplDelegateRef;
|
typedef id<WindowImplDelegateProtocol,NSObject> WindowImplDelegateRef;
|
||||||
|
|
||||||
@class NSAutoreleasePool;
|
|
||||||
typedef NSAutoreleasePool* NSAutoreleasePoolRef;
|
|
||||||
|
|
||||||
@class NSOpenGLContext;
|
@class NSOpenGLContext;
|
||||||
typedef NSOpenGLContext* NSOpenGLContextRef;
|
typedef NSOpenGLContext* NSOpenGLContextRef;
|
||||||
|
|
||||||
@ -51,7 +48,6 @@ typedef NSOpenGLContext* NSOpenGLContextRef;
|
|||||||
typedef unsigned short unichar; // See NSString.h
|
typedef unsigned short unichar; // See NSString.h
|
||||||
|
|
||||||
typedef void* WindowImplDelegateRef;
|
typedef void* WindowImplDelegateRef;
|
||||||
typedef void* NSAutoreleasePoolRef;
|
|
||||||
typedef void* NSOpenGLContextRef;
|
typedef void* NSOpenGLContextRef;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -326,7 +322,6 @@ private:
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplDelegateRef myDelegate; ///< Implementation in Obj-C.
|
WindowImplDelegateRef myDelegate; ///< Implementation in Obj-C.
|
||||||
NSAutoreleasePoolRef myPool; ///< Memory manager for this class.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#import <SFML/Window/OSX/SFWindowController.h>
|
#import <SFML/Window/OSX/SFWindowController.h>
|
||||||
#import <SFML/Window/OSX/SFViewController.h>
|
#import <SFML/Window/OSX/SFViewController.h>
|
||||||
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
#import <SFML/Window/OSX/cpp_objc_conversion.h>
|
||||||
|
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -44,8 +45,8 @@ namespace priv
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplCocoa::WindowImplCocoa(WindowHandle handle)
|
WindowImplCocoa::WindowImplCocoa(WindowHandle handle)
|
||||||
{
|
{
|
||||||
// Create the pool.
|
// Ask for a pool.
|
||||||
myPool = [[NSAutoreleasePool alloc] init];
|
RetainPool();
|
||||||
|
|
||||||
// Treat the handle as it real type
|
// Treat the handle as it real type
|
||||||
id nsHandle = (id)handle;
|
id nsHandle = (id)handle;
|
||||||
@ -94,8 +95,8 @@ WindowImplCocoa::WindowImplCocoa(VideoMode mode,
|
|||||||
// Transform the app process.
|
// Transform the app process.
|
||||||
SetUpProcess();
|
SetUpProcess();
|
||||||
|
|
||||||
// Create the pool.
|
// Ask for a pool.
|
||||||
myPool = [[NSAutoreleasePool alloc] init];
|
RetainPool();
|
||||||
|
|
||||||
// Don't forget to update our parent (that is, WindowImpl) size :
|
// Don't forget to update our parent (that is, WindowImpl) size :
|
||||||
myWidth = mode.Width;
|
myWidth = mode.Width;
|
||||||
@ -113,7 +114,8 @@ WindowImplCocoa::~WindowImplCocoa()
|
|||||||
[myDelegate closeWindow];
|
[myDelegate closeWindow];
|
||||||
|
|
||||||
[myDelegate release];
|
[myDelegate release];
|
||||||
[myPool drain];
|
|
||||||
|
ReleasePool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user