mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
OSX/MACOS: Make [CocoaView get] honour the +0 "get" convention
+[CocoaView get] is a cached-singleton accessor. By Cocoa
convention a method whose name does not start with new / alloc /
copy / mutableCopy returns a +0 (unretained) reference; the
singleton is kept alive by the storage it is cached in.
The existing implementation violated that convention on the
first-time path: it did [CocoaView new] (+1) and handed the
pointer to nsview_set_ptr, which was a raw `g_instance = p;` -
no retain. The caller then received a +1 return on the first
call but +0 on every call thereafter. Under ARC the strong
static would retain on store so it was self-consistent, but
under MRR the first-ever caller had an unbalanced +1 the code
never handled - a small process-lifetime leak. A prior commit
(e9279a8) leaned into the +0 assumption by adding RARCH_RETAIN
wrappers in ui_cocoa.m, which silently turned that +1 into a
+2 leak whenever -setViewType: was called for a singleton-
backed view type on its first use.
Two changes, both behind the existing RARCH_* macros so ARC
builds see no-ops:
- +[CocoaView get]: autorelease the freshly-allocated instance
before storing. The returned pointer is now +0 on every path,
matching the get naming convention.
- nsview_set_ptr: take a proper strong reference for the
g_instance slot (retain new, release old). g_instance is
now the single owner of the singleton's +1, matching how the
rest of the codebase already treats it (never nil-ed, never
explicitly released - so the retain lives for the process
lifetime, which is the intent).
Adds #include <defines/cocoa_defines.h> to cocoa_common.m for
RARCH_RETAIN / RARCH_RELEASE / RARCH_AUTORELEASE. The include
path is already on every Apple build config (already used by
ui_cocoa.m, dispserv_apple.m, coreaudio.c).
No behavioural change under ARC. On MRR, plugs the first-call
+1 leak and cancels the +2 over-retain that e9279a8's RARCH_RETAIN
wrappers would otherwise produce.
This commit is contained in:
1 parent
e0b7b9b216
commit
0062608a13
1 file changed
+31
-2
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <compat/apple_compat.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <defines/cocoa_defines.h>
|
||||
|
||||
#include "cocoa_common.h"
|
||||
#include "apple_platform.h"
|
||||
@@ -206,7 +207,17 @@ void rarch_stop_draw_observer(void)
|
||||
CocoaView *view = (BRIDGE CocoaView*)nsview_get_ptr();
|
||||
if (!view)
|
||||
{
|
||||
view = [CocoaView new];
|
||||
/* +new returns +1 owned by the caller. Autorelease before
|
||||
* handing to nsview_set_ptr, which takes its own retain for
|
||||
* the process-lifetime g_instance slot. Net result: the
|
||||
* returned pointer obeys the Cocoa +0 "get" convention on
|
||||
* both the first call (where we allocate) and every
|
||||
* subsequent call (where we just read g_instance) - so
|
||||
* callers do not have to guess the retain count. Under ARC
|
||||
* RARCH_AUTORELEASE is a no-op; the strong local's end-of-
|
||||
* scope release balances +new's +1 after g_instance's
|
||||
* storeStrong has taken its own retain. */
|
||||
view = RARCH_AUTORELEASE([CocoaView new]);
|
||||
nsview_set_ptr(view);
|
||||
#if defined(IOS)
|
||||
view.displayLink = [CADisplayLink displayLinkWithTarget:view selector:@selector(step:)];
|
||||
@@ -936,7 +947,25 @@ void *nsview_get_ptr(void)
|
||||
return (BRIDGE void *)g_instance;
|
||||
}
|
||||
|
||||
void nsview_set_ptr(CocoaView *p) { g_instance = p; }
|
||||
void nsview_set_ptr(CocoaView *p)
|
||||
{
|
||||
/* g_instance is the process-lifetime strong reference to the
|
||||
* CocoaView singleton. Under MRR we must explicitly retain the
|
||||
* new value and release the old one so g_instance owns a
|
||||
* balanced +1 across reassignments. In practice there is only
|
||||
* one caller (+[CocoaView get] on its first-time path), but the
|
||||
* invariant matters: callers treat [CocoaView get] as a +0 "get"
|
||||
* accessor, and that only holds if g_instance is the one keeping
|
||||
* the view alive. Under ARC RARCH_RETAIN and RARCH_RELEASE are
|
||||
* no-ops; the static __strong pointer does retain/release via
|
||||
* objc_storeStrong when assigned. */
|
||||
if (g_instance != p)
|
||||
{
|
||||
RARCH_RETAIN(p);
|
||||
RARCH_RELEASE(g_instance);
|
||||
g_instance = p;
|
||||
}
|
||||
}
|
||||
|
||||
CocoaView *cocoaview_get(void)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user