Re: -[NSGarbageCollection disableCollectorForPointer:] ?
Re: -[NSGarbageCollection disableCollectorForPointer:] ?
- Subject: Re: -[NSGarbageCollection disableCollectorForPointer:] ?
- From: Michael Link <email@hidden>
- Date: Wed, 15 Oct 2008 23:47:56 -0500
I actually went with using NSAllocateCollectable(NSScannedOption) and
that seems to be working well. Thanks.
--
Michael
On Oct 15, 2008, at 9:21 PM, Ken Ferry wrote:
Or you could malloc the memory for the buffer (free'ing it when
you're done) and disable/enable collection on any objects pointers
you store in it that you also want to keep alive. Maybe that's
easier to understand.
(Any time you use disableCollectorForPointer is a possible leak, by
the way. The object will be rooted until you reenable collection,
so don't try to reenable collection from within the finalizer of an
object that the rooted object will keep alive. That's an
uncollectable cycle.)
-Ken
On Wed, Oct 15, 2008 at 4:45 PM, Ken Ferry <email@hidden> wrote:
> What I did try was
> 'NSPointerFunctionsStrongMemory|
NSPointerFunctionsObjectPointerPersonality'
> which does work even though some of the pointers aren't objects
and this
> doesn't seem quite correct but since I'm using GC
> NSPointerFunctionsObjectPointerPersonality seems nearly equivalent
to
> NSPointerFunctionsOpaquePersonality as long as description isn't
called.
I see.. I think it's a bug that NSPointerFunctionsStrongMemory|
NSPointerFunctionsOpaqueMemory is rejected.
It's probably not very future safe to add non-objects with the
object personality. You might prefer to use
NSAllocateCollectable(NSScannedOption) and forego the pointer
array. This allocates a chunk of memory that is:
(1) Collected by the collector when unreachable by strong reference
chain from a gc-root.
(2) Conservatively scanned.
To keep the memory alive when used as the void* contextInfo, you'd
still need to use -[NSGarbageCollector disableCollectorForPointer:].
The main gotcha is that any stores of gc objects into the buffer
need to generate write barriers, which are calls into the objective-
c library that let the collector know that the the buffer has
changed and needs to be rescanned next time a collection runs. This
should Just Work provided the type of the buffer is __strong, but
you can put doubt to rest by checking that the compiler emitted the
function calls. In Xcode, right click and choose "Show Assembly
Code", then look for the calls. For example, this
- (void)writeToCollectableMemory:(NSObject *)object {
int bufferLength = 5;
__strong void **buffer = (__strong
void**)NSAllocateCollectable(sizeof(void*)*bufferLength,
NSScannedOption);
buffer[3] = [[NSObject alloc] init];
…
compiles to this. objc_assign_strongCast is the function call.
"-[MyBlockOperation writeToCollectableMemory:]":
LFB672:
LM221:
LVL93:
pushl ëp
LCFI337:
movl %esp, ëp
LCFI338:
pushl %esi
LCFI339:
pushl ëx
LCFI340:
subl $16, %esp
LCFI341:
call L245
"L00000000076$pb":
L245:
popl ëx
LM222:
movl $1, 4(%esp)
movl $20, (%esp)
call _NSAllocateCollectable
movl êx, %esi
LM223:
movl L_OBJC_SELECTOR_REFERENCES_3-"L00000000076$pb"(ëx), êx
movl êx, 4(%esp)
movl L_OBJC_CLASS_REFERENCES_0-"L00000000076$pb"(ëx), êx
movl êx, (%esp)
call _objc_msgSend
movl L_OBJC_SELECTOR_REFERENCES_4-"L00000000076$pb"(ëx), íx
movl íx, 4(%esp)
movl êx, (%esp)
call _objc_msgSend
leal 12(%esi), íx
movl íx, 4(%esp)
movl êx, (%esp)
call _objc_assign_strongCast
…
-Ken
Cocoa Frameworks
On Wed, Oct 15, 2008 at 9:32 AM, Michael Link <email@hidden>
wrote:
> That makes sense, although
> 'NSPointerFunctionsStrongMemory|NSPointerFunctionsOpaqueMemory'
gives the
> error:
>
> *** -[NSPointerArray initWithOptions:] Requested configuration not
> supported.
>
> What I did try was
> 'NSPointerFunctionsStrongMemory|
NSPointerFunctionsObjectPointerPersonality'
> which does work even though some of the pointers aren't objects
and this
> doesn't seem quite correct but since I'm using GC
> NSPointerFunctionsObjectPointerPersonality seems nearly equivalent
to
> NSPointerFunctionsOpaquePersonality as long as description isn't
called.
>
> --
> Michael
>
> On Oct 15, 2008, at 1:08 AM, Ken Ferry wrote:
>
>> Hi Michael,
>>
>> NSPointerFunctionsStrongMemory|NSPointerFunctionsOpaqueMemory
doesn't
>> make sense. You're meant to specify only one of the memory
options and
>> only one of the personality options.
>>
>> Due to the way the bitfield work, your invocation is the same as
>> NSPointerFunctionsOpaqueMemory|NSPointerFunctionsOpaquePersonality.
>> This is the mode in which the pointer array is completely hands-
off.
>> It acts like a C array.
>>
>> Try NSPointerFunctionsStrongMemory|
NSPointerFunctionsOpaquePersonality.
>> That sounds right to me, though I get confused with the pointer
>> functions too.
>>
>> -Ken
>>
>> On Tue, Oct 14, 2008 at 9:43 PM, Michael Link <email@hidden>
wrote:
>>>
>>> I have a situation where I create an NSPointerArray on the stack
by:
>>>
>>> pointers = [NSPointerArray
>>>
>>> pointerArrayWithOptions:NSPointerFunctionsStrongMemory|
NSPointerFunctionsOpaqueMemory|NSPointerFunctionsOpaquePersonality];
>>>
>>> I then go about adding a few objects a selector and a pointer
>>> (contextInfo
>>> that could point to anything even a non-object) to the pointer
array.
>>>
>>> I then call:
>>>
>>> [[NSGarbageCollector defaultCollector]
>>> disableCollectorForPointer:pointers];
>>>
>>> The pointer array is then passed as the contextInfo for another
method
>>> (which turns out to be a weak reference), but isn't garbage
collected due
>>> to
>>> the previous call. The interesting part turns out that the
object at
>>> index 0
>>> (NSError* in this case) in the pointer array is garbage collected
>>> (probably
>>> because it was a variable in the function that called us). The
pointer
>>> array
>>> is configured to use strong references therefore index 0 isn't
set to
>>> NULL
>>> and something else is located at that memory (sometimes a
different
>>> object,
>>> sometimes garbage memory).
>>>
>>> If I use:
>>>
>>> [[NSGarbageCollector defaultCollector]
>>> disableCollectorForPointer:[pointers
>>> pointerAtIndex:0]];
>>>
>>> nothing bad happens and that object isn't collected.
>>>
>>> According to the documentation for disableCollectorForPointer:
shouldn't
>>> the
>>> pointer array be considered a new root object, and none of it's
pointers
>>> collected? Especially since it uses strong references?
>>>
>>> --
>>> Michael
>>> _______________________________________________
>>>
>>> Cocoa-dev mailing list (email@hidden)
>>>
>>> Please do not post admin requests or moderator comments to the
list.
>>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>>
>>> Help/Unsubscribe/Update your Subscription:
>>>
>>> This email sent to email@hidden
>>>
>>
>>
>
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden