diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 55cb17f18..2fa013fd7 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -182,7 +182,7 @@ elseif(SFML_OS_MACOSX) ${SRCROOT}/OSX/WindowImplCocoa.hpp ${SRCROOT}/OSX/WindowImplCocoa.mm ${SRCROOT}/OSX/WindowImplDelegateProtocol.h - ${SRCROOT}/OSX/AutoreleasePoolWrapper.h + ${SRCROOT}/OSX/AutoreleasePoolWrapper.hpp ${SRCROOT}/OSX/AutoreleasePoolWrapper.mm ) source_group("mac" FILES ${PLATFORM_SRC}) diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h b/src/SFML/Window/OSX/AutoreleasePoolWrapper.hpp similarity index 55% rename from src/SFML/Window/OSX/AutoreleasePoolWrapper.h rename to src/SFML/Window/OSX/AutoreleasePoolWrapper.hpp index cc09d0946..cacbb591a 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.h +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.hpp @@ -23,15 +23,54 @@ // //////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////// -/// \brief Ensure one autorelease pool is available on this thread -/// -//////////////////////////////////////////////////////////// -void ensureThreadHasPool(void); - +#ifndef SFML_AUTORELEASEPOOL_HPP +#define SFML_AUTORELEASEPOOL_HPP //////////////////////////////////////////////////////////// -/// \brief Drain the thread's pool but keep it alive +/// Predefine OBJ-C classes +//////////////////////////////////////////////////////////// +#ifdef __OBJC__ + +@class NSAutoreleasePool; +typedef NSAutoreleasePool* NSAutoreleasePoolRef; + +#else // If C++ + +typedef void* NSAutoreleasePoolRef; + +#endif + +namespace sf +{ + +//////////////////////////////////////////////////////////// +/// \brief Wraps an NSAutoreleasePool that is created when the object is +/// constructed and is drained when the object is destroyed. /// //////////////////////////////////////////////////////////// -void drainThreadPool(void); +class AutoreleasePool +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Construct a new NSAutoreleasePool. + /// + //////////////////////////////////////////////////////////// + AutoreleasePool(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor. Drains the autorelease pool. + /// + //////////////////////////////////////////////////////////// + ~AutoreleasePool(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + NSAutoreleasePoolRef pool; ///< The autorelease pool. +}; + +} // namespace sf + +#endif // SFML_AUTORELEASEPOOL_HPP diff --git a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm index b0c46438a..7d707f49a 100644 --- a/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm +++ b/src/SFML/Window/OSX/AutoreleasePoolWrapper.mm @@ -26,80 +26,25 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include -#include -#import +#include + #import - -//////////////////////////////////////////////////////////// -/// 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). -/// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -// Private data -//////////////////////////////////////////////////////////// -static pthread_key_t poolKey; -static pthread_once_t initOnceToken = PTHREAD_ONCE_INIT; - - -//////////////////////////////////////////////////////////// -/// \brief (local function) Drain one more time the pool -/// but this time don't create a new one. -/// -//////////////////////////////////////////////////////////// -static void destroyPool(void* data) +namespace sf +{ + +//////////////////////////////////////////////////////// +AutoreleasePool::AutoreleasePool() +{ + pool = [[NSAutoreleasePool alloc] init]; +} + + +//////////////////////////////////////////////////////// +AutoreleasePool::~AutoreleasePool() { - NSAutoreleasePool* pool = (NSAutoreleasePool*)data; [pool drain]; } - -//////////////////////////////////////////////////////////// -/// \brief (local function) Init the pthread key for the pool -/// -//////////////////////////////////////////////////////////// -static void createPoolKey(void) -{ - pthread_key_create(&poolKey, destroyPool); -} - - -//////////////////////////////////////////////////////////// -/// \brief (local function) Store a new pool for this thread -/// -//////////////////////////////////////////////////////////// -static void createNewPool(void) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - pthread_setspecific(poolKey, pool); -} - - -//////////////////////////////////////////////////////////// -void ensureThreadHasPool(void) -{ - pthread_once(&initOnceToken, createPoolKey); - if (pthread_getspecific(poolKey) == NULL) - { - createNewPool(); - } -} - - -//////////////////////////////////////////////////////////// -void drainThreadPool(void) -{ - void* data = pthread_getspecific(poolKey); - assert(data != NULL); - - // Drain the pool but keep it alive by creating a new one - destroyPool(data); - createNewPool(); -} - +} // namespace sf diff --git a/src/SFML/Window/OSX/ClipboardImpl.mm b/src/SFML/Window/OSX/ClipboardImpl.mm index 69eb94096..858e35ace 100644 --- a/src/SFML/Window/OSX/ClipboardImpl.mm +++ b/src/SFML/Window/OSX/ClipboardImpl.mm @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include #import @@ -37,6 +38,7 @@ namespace priv //////////////////////////////////////////////////////////// String ClipboardImpl::getString() { + AutoreleasePool pool; NSPasteboard* pboard = [NSPasteboard generalPasteboard]; NSString* data = [pboard stringForType:NSPasteboardTypeString]; @@ -50,6 +52,7 @@ String ClipboardImpl::getString() //////////////////////////////////////////////////////////// void ClipboardImpl::setString(const String& text) { + AutoreleasePool pool; std::basic_string utf8 = text.toUtf8(); NSString* data = [[NSString alloc] initWithBytes:utf8.data() length:utf8.length() diff --git a/src/SFML/Window/OSX/CursorImpl.mm b/src/SFML/Window/OSX/CursorImpl.mm index 51e266bb3..7ee80158c 100644 --- a/src/SFML/Window/OSX/CursorImpl.mm +++ b/src/SFML/Window/OSX/CursorImpl.mm @@ -27,8 +27,8 @@ // Headers //////////////////////////////////////////////////////////// #include +#include -#import #import #import @@ -53,17 +53,13 @@ namespace priv { //////////////////////////////////////////////////////////// -CursorImpl::CursorImpl() : -m_cursor(nil) -{ - // Just ask for a pool - ensureThreadHasPool(); -} +CursorImpl::CursorImpl() : m_cursor(nil) {} //////////////////////////////////////////////////////////// CursorImpl::~CursorImpl() { + AutoreleasePool pool; [m_cursor release]; } @@ -71,6 +67,7 @@ CursorImpl::~CursorImpl() //////////////////////////////////////////////////////////// bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot) { + AutoreleasePool pool; if (m_cursor) { [m_cursor release]; @@ -89,6 +86,7 @@ bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hot //////////////////////////////////////////////////////////// bool CursorImpl::loadFromSystem(Cursor::Type type) { + AutoreleasePool pool; NSCursor* newCursor = nil; switch (type) diff --git a/src/SFML/Window/OSX/InputImpl.mm b/src/SFML/Window/OSX/InputImpl.mm index 934470da8..a5c200a13 100644 --- a/src/SFML/Window/OSX/InputImpl.mm +++ b/src/SFML/Window/OSX/InputImpl.mm @@ -28,6 +28,7 @@ //////////////////////////////////////////////////////////// #include #include +#include #include #include #include @@ -125,6 +126,7 @@ SFOpenGLView* getSFOpenGLViewFromSFMLWindow(const WindowBase& window) //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { + AutoreleasePool pool; return HIDInputManager::getInstance().isKeyPressed(key); } @@ -139,6 +141,7 @@ void InputImpl::setVirtualKeyboardVisible(bool /*visible*/) //////////////////////////////////////////////////////////// bool InputImpl::isMouseButtonPressed(Mouse::Button button) { + AutoreleasePool pool; NSUInteger state = [NSEvent pressedMouseButtons]; NSUInteger flag = 1 << button; return (state & flag) != 0; @@ -148,6 +151,7 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) //////////////////////////////////////////////////////////// Vector2i InputImpl::getMousePosition() { + AutoreleasePool pool; // Reverse Y axis to match SFML coord. NSPoint pos = [NSEvent mouseLocation]; pos.y = sf::VideoMode::getDesktopMode().height - pos.y; @@ -160,6 +164,7 @@ Vector2i InputImpl::getMousePosition() //////////////////////////////////////////////////////////// Vector2i InputImpl::getMousePosition(const WindowBase& relativeTo) { + AutoreleasePool pool; SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); // No view ? @@ -177,6 +182,7 @@ Vector2i InputImpl::getMousePosition(const WindowBase& relativeTo) //////////////////////////////////////////////////////////// void InputImpl::setMousePosition(const Vector2i& position) { + AutoreleasePool pool; // Here we don't need to reverse the coordinates. int scale = [[NSScreen mainScreen] backingScaleFactor]; CGPoint pos = CGPointMake(position.x / scale, position.y / scale); @@ -195,6 +201,7 @@ void InputImpl::setMousePosition(const Vector2i& position) //////////////////////////////////////////////////////////// void InputImpl::setMousePosition(const Vector2i& position, const WindowBase& relativeTo) { + AutoreleasePool pool; SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); // No view ? diff --git a/src/SFML/Window/OSX/JoystickImpl.cpp b/src/SFML/Window/OSX/JoystickImpl.cpp index 26b1727b2..f2a159a25 100644 --- a/src/SFML/Window/OSX/JoystickImpl.cpp +++ b/src/SFML/Window/OSX/JoystickImpl.cpp @@ -27,6 +27,7 @@ // Headers //////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -106,6 +107,7 @@ void JoystickImpl::cleanup() //////////////////////////////////////////////////////////// bool JoystickImpl::isConnected(unsigned int index) { + AutoreleasePool pool; bool state = false; // Is the index-th joystick connected? // First, let's check if the device was previously detected: @@ -180,6 +182,7 @@ bool JoystickImpl::isConnected(unsigned int index) //////////////////////////////////////////////////////////// bool JoystickImpl::open(unsigned int index) { + AutoreleasePool pool; m_index = index; m_hat = NULL; Location deviceLoc = m_locationIDs[index]; // The device we need to load @@ -325,6 +328,7 @@ bool JoystickImpl::open(unsigned int index) //////////////////////////////////////////////////////////// void JoystickImpl::close() { + AutoreleasePool pool; for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) CFRelease(*it); m_buttons.clear(); @@ -345,6 +349,7 @@ void JoystickImpl::close() //////////////////////////////////////////////////////////// JoystickCaps JoystickImpl::getCapabilities() const { + AutoreleasePool pool; JoystickCaps caps; // Buttons: @@ -364,6 +369,7 @@ JoystickCaps JoystickImpl::getCapabilities() const //////////////////////////////////////////////////////////// Joystick::Identification JoystickImpl::getIdentification() const { + AutoreleasePool pool; return m_identification; } @@ -371,6 +377,7 @@ Joystick::Identification JoystickImpl::getIdentification() const //////////////////////////////////////////////////////////// JoystickState JoystickImpl::update() { + AutoreleasePool pool; static const JoystickState disconnectedState; // return this if joystick was disconnected JoystickState state; // otherwise return that state.connected = true; diff --git a/src/SFML/Window/OSX/SFApplication.m b/src/SFML/Window/OSX/SFApplication.m index 8a98a8a0b..8365c3a2d 100644 --- a/src/SFML/Window/OSX/SFApplication.m +++ b/src/SFML/Window/OSX/SFApplication.m @@ -52,6 +52,8 @@ //////////////////////////////////////////////////////// +(void)setUpMenuBar { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [SFApplication sharedApplication]; // Make sure NSApp exists // Set the main menu bar @@ -76,6 +78,8 @@ NSMenu* windowMenu = [[SFApplication newWindowMenu] autorelease]; [windowItem setSubmenu:windowMenu]; [NSApp setWindowsMenu:windowMenu]; + + [pool drain]; } @@ -98,6 +102,8 @@ // -------------------- // Quit AppName Command+Q + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSString* appName = [SFApplication applicationName]; // APPLE MENU @@ -154,6 +160,8 @@ action:@selector(terminate:) keyEquivalent:@"q"]; + [pool drain]; + return appleMenu; } diff --git a/src/SFML/Window/OSX/SFContext.mm b/src/SFML/Window/OSX/SFContext.mm index 776e3c531..358172afd 100644 --- a/src/SFML/Window/OSX/SFContext.mm +++ b/src/SFML/Window/OSX/SFContext.mm @@ -26,14 +26,13 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include #include #include #include #include -#import - namespace sf { namespace priv @@ -46,9 +45,7 @@ m_context(0), m_view(0), m_window(0) { - // Ask for a pool. - ensureThreadHasPool(); - + AutoreleasePool pool; // Create the context createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, @@ -63,9 +60,7 @@ m_context(0), m_view(0), m_window(0) { - // Ask for a pool. - ensureThreadHasPool(); - + AutoreleasePool pool; // Create the context. createContext(shared, bitsPerPixel, settings); @@ -82,12 +77,10 @@ m_context(0), m_view(0), m_window(0) { + AutoreleasePool pool; // Ensure the process is setup in order to create a valid window. WindowImplCocoa::setUpProcess(); - // Ask for a pool. - ensureThreadHasPool(); - // Create the context. createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); @@ -106,6 +99,7 @@ m_window(0) //////////////////////////////////////////////////////////// SFContext::~SFContext() { + AutoreleasePool pool; // Notify unshared OpenGL resources of context destruction cleanupUnsharedResources(); @@ -124,6 +118,7 @@ SFContext::~SFContext() //////////////////////////////////////////////////////////// GlFunctionPointer SFContext::getFunction(const char* name) { + AutoreleasePool pool; static void* image = NULL; if (!image) @@ -136,6 +131,7 @@ GlFunctionPointer SFContext::getFunction(const char* name) //////////////////////////////////////////////////////////// bool SFContext::makeCurrent(bool current) { + AutoreleasePool pool; if (current) { [m_context makeCurrentContext]; @@ -152,6 +148,7 @@ bool SFContext::makeCurrent(bool current) //////////////////////////////////////////////////////////// void SFContext::display() { + AutoreleasePool pool; [m_context flushBuffer]; } @@ -159,6 +156,7 @@ void SFContext::display() //////////////////////////////////////////////////////////// void SFContext::setVerticalSyncEnabled(bool enabled) { + AutoreleasePool pool; GLint swapInterval = enabled ? 1 : 0; [m_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; @@ -170,6 +168,7 @@ void SFContext::createContext(SFContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { + AutoreleasePool pool; // Save the settings. (OpenGL version is updated elsewhere.) m_settings = settings; diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index b4453a98a..94e38dce3 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -26,10 +26,10 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include #include -#import #import #import #import @@ -59,6 +59,7 @@ namespace //////////////////////////////////////////////////////// void hideMouseCursor() { + AutoreleasePool pool; if (!isCursorHidden) { [NSCursor hide]; @@ -70,6 +71,7 @@ void hideMouseCursor() //////////////////////////////////////////////////////// void showMouseCursor() { + AutoreleasePool pool; if (isCursorHidden) { [NSCursor unhide]; @@ -84,9 +86,7 @@ void showMouseCursor() WindowImplCocoa::WindowImplCocoa(WindowHandle handle) : m_showCursor(true) { - // Ask for a pool. - ensureThreadHasPool(); - + AutoreleasePool pool; // Treat the handle as it real type id nsHandle = (id)handle; if ([nsHandle isKindOfClass:[NSWindow class]]) @@ -126,12 +126,10 @@ WindowImplCocoa::WindowImplCocoa(VideoMode mode, const ContextSettings& /*settings*/) : m_showCursor(true) { + AutoreleasePool pool; // Transform the app process. setUpProcess(); - // Ask for a pool. - ensureThreadHasPool(); - // Use backing size scaleInWidthHeight(mode, nil); @@ -147,8 +145,12 @@ m_showCursor(true) //////////////////////////////////////////////////////////// WindowImplCocoa::~WindowImplCocoa() { + AutoreleasePool pool; [m_delegate closeWindow]; - + // Tell the window/view controller (and the OpenGL view) that the delegate + // (this object) no longer exists to prevent events being sent to the window + // after it has been deleted. + [m_delegate setRequesterTo:0]; [m_delegate release]; // Put the next window in front, if any. @@ -159,16 +161,13 @@ WindowImplCocoa::~WindowImplCocoa() if ([nextWindow isVisible]) [nextWindow makeKeyAndOrderFront:nil]; } - - drainThreadPool(); // Make sure everything was freed - // This solve some issue when sf::Window::Create is called for the - // second time (nothing was render until the function was called again) } //////////////////////////////////////////////////////////// void WindowImplCocoa::applyContext(NSOpenGLContextRef context) const { + AutoreleasePool pool; [m_delegate applyContext:context]; } @@ -176,6 +175,7 @@ void WindowImplCocoa::applyContext(NSOpenGLContextRef context) const //////////////////////////////////////////////////////////// void WindowImplCocoa::setUpProcess(void) { + AutoreleasePool pool; static bool isTheProcessSetAsApplication = false; if (!isTheProcessSetAsApplication) @@ -398,8 +398,8 @@ void WindowImplCocoa::textEntered(unichar charcode) //////////////////////////////////////////////////////////// void WindowImplCocoa::processEvents() { + AutoreleasePool pool; [m_delegate processEvent]; - drainThreadPool(); // Reduce memory footprint } #pragma mark @@ -408,6 +408,7 @@ void WindowImplCocoa::processEvents() //////////////////////////////////////////////////////////// WindowHandle WindowImplCocoa::getSystemHandle() const { + AutoreleasePool pool; return [m_delegate getSystemHandle]; } @@ -415,6 +416,7 @@ WindowHandle WindowImplCocoa::getSystemHandle() const //////////////////////////////////////////////////////////// Vector2i WindowImplCocoa::getPosition() const { + AutoreleasePool pool; NSPoint pos = [m_delegate position]; sf::Vector2i ret(pos.x, pos.y); scaleOutXY(ret, m_delegate); @@ -425,6 +427,7 @@ Vector2i WindowImplCocoa::getPosition() const //////////////////////////////////////////////////////////// void WindowImplCocoa::setPosition(const Vector2i& position) { + AutoreleasePool pool; sf::Vector2i backingPosition = position; scaleInXY(backingPosition, m_delegate); [m_delegate setWindowPositionToX:backingPosition.x Y:backingPosition.y]; @@ -434,6 +437,7 @@ void WindowImplCocoa::setPosition(const Vector2i& position) //////////////////////////////////////////////////////////// Vector2u WindowImplCocoa::getSize() const { + AutoreleasePool pool; NSSize size = [m_delegate size]; Vector2u ret(size.width, size.height); scaleOutXY(ret, m_delegate); @@ -453,6 +457,7 @@ void WindowImplCocoa::setSize(const Vector2u& size) //////////////////////////////////////////////////////////// void WindowImplCocoa::setTitle(const String& title) { + AutoreleasePool pool; [m_delegate changeTitle:sfStringToNSString(title)]; } @@ -460,6 +465,7 @@ void WindowImplCocoa::setTitle(const String& title) //////////////////////////////////////////////////////////// void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) { + AutoreleasePool pool; [m_delegate setIconTo:width by:height with:pixels]; } @@ -467,6 +473,7 @@ void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uin //////////////////////////////////////////////////////////// void WindowImplCocoa::setVisible(bool visible) { + AutoreleasePool pool; if (visible) [m_delegate showWindow]; else @@ -477,6 +484,7 @@ void WindowImplCocoa::setVisible(bool visible) //////////////////////////////////////////////////////////// void WindowImplCocoa::setMouseCursorVisible(bool visible) { + AutoreleasePool pool; m_showCursor = visible; // If the mouse is over the window, we apply the new setting @@ -493,6 +501,7 @@ void WindowImplCocoa::setMouseCursorVisible(bool visible) //////////////////////////////////////////////////////////// void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed) { + AutoreleasePool pool; [m_delegate setCursorGrabbed:grabbed]; } @@ -500,6 +509,7 @@ void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed) //////////////////////////////////////////////////////////// void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor) { + AutoreleasePool pool; [m_delegate setCursor:cursor.m_cursor]; } @@ -507,6 +517,7 @@ void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor) //////////////////////////////////////////////////////////// void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) { + AutoreleasePool pool; if (enabled) [m_delegate enableKeyRepeat]; else @@ -517,6 +528,7 @@ void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplCocoa::requestFocus() { + AutoreleasePool pool; [m_delegate requestFocus]; } @@ -524,6 +536,7 @@ void WindowImplCocoa::requestFocus() //////////////////////////////////////////////////////////// bool WindowImplCocoa::hasFocus() const { + AutoreleasePool pool; return [m_delegate hasFocus]; }