Re: Garbage collector

2010-06-08 Thread Thomas Davie
At present, the iPhone SDK does not support garbage collection, so you're best 
off at least making it GC supported, rather than required.

Bob

On 8 Jun 2010, at 11:48, Takeichi Kanzaki Cabrera wrote:

> Hi all, I'm beginning with an application for Mac OS X that in a
> future could become into an iphone app, could I use the garbage
> collector or is better don't use it?
> 
> Regards,
> Takeichi
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> 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:
> http://lists.apple.com/mailman/options/cocoa-dev/tom.davie%40gmail.com
> 
> This email sent to tom.da...@gmail.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Garbage collector

2010-06-08 Thread Takeichi Kanzaki Cabrera
Hi all, I'm beginning with an application for Mac OS X that in a
future could become into an iphone app, could I use the garbage
collector or is better don't use it?

Regards,
Takeichi
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Garbage collector

2010-05-23 Thread paul Fultz
How do I use cocoas garbage collector in c++? It seems to be implemented in c++ 
with libauto:
http://www.opensource.apple.com/source/libauto/libauto-77.1/README.html?f=text
But I cant seem to find that much documentation on it.
Thanks,
Paul



  
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Sheets, blocks and garbage collector

2010-02-06 Thread Frédéric Testuz
Le 6 févr. 2010 à 17:55, Michael Ash a écrit :

> 2010/2/6 Frédéric Testuz :
>> Hi all,
>> 
>> I'm beginning a new application targeting Snow Leopard only. So I want to 
>> use the new tools (blocks) and garbage collection (GC). It will be my first 
>> application using GC.
>> 
>> I read some sites on GC and blocks. In the blog of Mike Ash I found some 
>> very interesting propositions. My question concerns his code for using block 
>> with sheets 
>> (http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html).
>>  Is this code works in GC ?
>> 
>> @implementation NSApplication (SheetAdditions)
>> 
>> - (void)beginSheet: (NSWindow *)sheet modalForWindow:(NSWindow *)docWindow 
>> didEndBlock: (void (^)(NSInteger returnCode))block
>> {
>> 
>> [self beginSheet: sheet
>>   modalForWindow: docWindow
>>   modalDelegate: self
>>   didEndSelector: @selector(my_blockSheetDidEnd:returnCode:contextInfo:)
>>   contextInfo: [block copy]];
>> }
>> 
>> - (void)my_blockSheetDidEnd: (NSWindow *)sheet returnCode: 
>> (NSInteger)returnCode contextInfo: (void *)contextInfo
>> {
>> void (^block)(NSInteger returnCode) = contextInfo;
>> block(returnCode);
>> [block release];
>> }
>> 
>> @end
>> 
>> I think, I have to replace [block copy] by CFRetain([block copy])
>> and [block release] by CFRelease(block).
> 
> I believe your GC modifications are correct. As you've presumably
> determined already, [block copy] alone isn't enough to keep the block
> alive through the void *.
> 
> If you happen to be writing dual-mode code, you can write code that
> works in both GC and refcounted environments by writing
> CFRetain([block copy]) in the first part and CFRelease(block); [block
> release]; in the second.

Thanks for your answer and for the completion. It will make the code reusable 
for another case without GC.

Frédéric___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Sheets, blocks and garbage collector

2010-02-06 Thread Michael Ash
2010/2/6 Frédéric Testuz :
> Hi all,
>
> I'm beginning a new application targeting Snow Leopard only. So I want to use 
> the new tools (blocks) and garbage collection (GC). It will be my first 
> application using GC.
>
> I read some sites on GC and blocks. In the blog of Mike Ash I found some very 
> interesting propositions. My question concerns his code for using block with 
> sheets 
> (http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html).
>  Is this code works in GC ?
>
> @implementation NSApplication (SheetAdditions)
>
> - (void)beginSheet: (NSWindow *)sheet modalForWindow:(NSWindow *)docWindow 
> didEndBlock: (void (^)(NSInteger returnCode))block
> {
>
> [self beginSheet: sheet
>        modalForWindow: docWindow
>        modalDelegate: self
>        didEndSelector: @selector(my_blockSheetDidEnd:returnCode:contextInfo:)
>        contextInfo: [block copy]];
> }
>
> - (void)my_blockSheetDidEnd: (NSWindow *)sheet returnCode: 
> (NSInteger)returnCode contextInfo: (void *)contextInfo
> {
> void (^block)(NSInteger returnCode) = contextInfo;
> block(returnCode);
> [block release];
> }
>
> @end
>
> I think, I have to replace [block copy] by CFRetain([block copy])
> and [block release] by CFRelease(block).

I believe your GC modifications are correct. As you've presumably
determined already, [block copy] alone isn't enough to keep the block
alive through the void *.

If you happen to be writing dual-mode code, you can write code that
works in both GC and refcounted environments by writing
CFRetain([block copy]) in the first part and CFRelease(block); [block
release]; in the second.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Sheets, blocks and garbage collector

2010-02-06 Thread Frédéric Testuz
Hi all,

I'm beginning a new application targeting Snow Leopard only. So I want to use 
the new tools (blocks) and garbage collection (GC). It will be my first 
application using GC.

I read some sites on GC and blocks. In the blog of Mike Ash I found some very 
interesting propositions. My question concerns his code for using block with 
sheets 
(http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html).
 Is this code works in GC ?

@implementation NSApplication (SheetAdditions)

- (void)beginSheet: (NSWindow *)sheet modalForWindow:(NSWindow *)docWindow 
didEndBlock: (void (^)(NSInteger returnCode))block
{

[self beginSheet: sheet
modalForWindow: docWindow
modalDelegate: self
didEndSelector: @selector(my_blockSheetDidEnd:returnCode:contextInfo:)
contextInfo: [block copy]];
}

- (void)my_blockSheetDidEnd: (NSWindow *)sheet returnCode: 
(NSInteger)returnCode contextInfo: (void *)contextInfo  
{
void (^block)(NSInteger returnCode) = contextInfo;
block(returnCode);
[block release];
}

@end

I think, I have to replace [block copy] by CFRetain([block copy])
and [block release] by CFRelease(block).

Frédéric

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to ease the burden on the Garbage Collector?

2009-10-10 Thread Jens Alfke


On Oct 10, 2009, at 1:14 AM, Gabriel Zachmann wrote:


So, is 20% CPU time for the GC thread normal?


That's a lot more than I'd expect based on what you're doing. Either  
you've got code you haven't shown us that's allocating a ton of  
objects during the animation, or some system framework (CoreAnimation,  
presumably) is allocating a lot of collectable objects.


I've used CA in some GC'd apps and haven't seen noticeable collection  
activity, but maybe I haven't used the same APIs as you.


What you need, I think, is to find out how to use Instruments or Shark  
to track only the allocation of collectable objects. Then you can see  
where that's occurring. I don't know how to do that, myself, but I'm  
sure someone here does.


—Jens___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to ease the burden on the Garbage Collector?

2009-10-10 Thread Gabriel Zachmann

Thanks for the response.

So, is 20% CPU time for the GC thread normal?



Yup, that shows about 20% (of a core) being spent in GC.



Best regards,
Gabriel.



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: How to ease the burden on the Garbage Collector?

2009-10-09 Thread Jens Alfke


On Oct 9, 2009, at 7:23 AM, Gabriel Zachmann wrote:


http://zach.in.tu-clausthal.de/tmp/malloc1.png
http://zach.in.tu-clausthal.de/tmp/malloc2.png
http://zach.in.tu-clausthal.de/tmp/malloc3.png


Those are showing all malloc operations. Most of those are not garbage- 
collected, so they don't affect GC time. (I'm not sure exactly what  
symbol to trace if you want to watch just GC allocations.)


Are you sure you aren't just seeing the GC thread sitting and  
waiting for something to do?

THat would mean that the GC thread does busy waiting, wouldn't it?



No, it's blocked on a semaphore. But it still shows up in samples or  
backtraces (in mach_message_trap, usually.)



Here are the top lines of the call tree that I see in Shark.
It seems to me that they all belong to the same thread, the GC thread.


Yup, that shows about 20% (of a core) being spent in GC.

—Jens___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to ease the burden on the Garbage Collector?

2009-10-09 Thread Gabriel Zachmann
It seems that about 20% of the time is spent in the Garbage  
Collector thread!


Which is a bit surprising to me, since I don't allocate a large  
number of objects (I think) -- just a small number of large objects  
(the images).


The collector only chews CPU when there are lots of allocation  
events (and, hopefully, deallocation events) that are causing the  
collector to believe it needs to do work.   Or when something is  
triggering the collector manually really often.


Have a look at ObjectAlloc & ObjectGraph in Instruments.   That  
should give you an idea if there are lots and lots of allocation  
events occurring and, if so, what they are.  From there, it is a  
matter of minimizing the number of allocations occurring.




If I understand the output of Instruments/ObjectAlloc correctly, it  
says there have been about 300,000 allocations withing about 1.5  
minutes.

Is that very much?

It also says that most of the allocations are CFStrings and small  
memory blocks (surprise surprise ;-) ), but looking at the instances  
it seems to me that I don't have much control over those.
(For instance, about half of the CFString's occur in the library  
CFNetwork in the functions initializeTLDMachine() and  
MemoryCookies::inflateFromData().)


Since I couldn't find a way to export the statistics in ASCII, I have  
made 3 screenshots, which you can see here:

http://zach.in.tu-clausthal.de/tmp/malloc1.png
http://zach.in.tu-clausthal.de/tmp/malloc2.png
http://zach.in.tu-clausthal.de/tmp/malloc3.png


For your information, here is an outline of my main loop (executed in  
ScreenSaverView's -animateOneFrame):


  get a new filename from a list of filenames
  CGImageSourceRef sourceRef = CGImageSourceCreateWithURL(..)
  check a few things in the sourceRef, such as image size
  CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0,  
NULL)
  [NSTimer scheduledTimerWithTimeInterval: 2.3 target: self selector:  
@selector(doGarbageCollection:) userInfo: nil repeats: NO];

  create new layer with contents = imageRef
  create a new animation and attach it to the new layer
  [CATransaction begin];
  [CATransaction setValue: [NSNumber numberWithFloat:  
fading_duration] forKey: kCATransactionAnimationDuration  ];

  [mainLayer_ replaceSublayer: currentLayer_ with: newlayer];
  currentLayer_ = newlayer;
  [CATransaction commit];

This gets executed every 5 seconds.

And here is what doGarbageCollection does:

- (void) doGarbageCollection: (NSTimer *) theTimer
{
if ( [NSGarbageCollector defaultCollector] )
[[NSGarbageCollector defaultCollector]  
collectExhaustively];// seems to work better than  
collectIfNeeded

}


I have tried omitting doGarbageCollection: , but then the  
screensaver's memory footprint grows until the memory is full, and  
then the animation stops for a second or 2 (you can see the memroy  
being freed in ActivityMonitor).


The judder I am concerned with seems to occur especially during image  
loading.


Again, the same code, when executed in the reference-counted  
environment (10.5) runs very smoothly, no judder whatsoever, not even  
during loading of an image.




Are you sure you aren't just seeing the GC thread sitting and  
waiting for something to do?


THat would mean that the GC thread does busy waiting, wouldn't it?

What are the "hot" methods/functions you see related to the GC  
thread? (many folks misread what Shark is telling them...)




Here are the top lines of the call tree that I see in Shark.
It seems to me that they all belong to the same thread, the GC thread.
So, one of the hot methods is  
Auto::MemoryScanner::scan_for_unmarked_blocks, isn't it?


0.0%31.7%   libSystem.B.dylib   start_wqthread
0.0%31.7%   libSystem.B.dylib_pthread_wqthread
0.0%31.7%   libSystem.B.dylib _dispatch_worker_thread2
0.0%20.4%   libSystem.B.dylib  _dispatch_queue_invoke
0.0%20.4%   libSystem.B.dylib   _dispatch_queue_drain
0.0%20.4%   libSystem.B.dylib
_dispatch_call_block_and_release
0.0%20.4%   libauto.dylib auto_collection_work(Auto::Zone*)
	0.0%	20.4%	libauto.dylib	   auto_collect_internal(Auto::Zone*,  
unsigned int)
	0.0%	20.3%	libauto.dylib	Auto::Zone::collect(bool, void*,  
unsigned long long*)

0.0%18.5%   libauto.dylibAuto::MemoryScanner::scan()
	0.6%	17.1%	libauto.dylib	   
Auto::MemoryScanner::scan_pending_until_done()
	0.6%	15.0%	libauto.dylib	
Auto::MemoryScanner::scan_for_unmarked_blocks(Auto::Subzone*, unsigned  
long, void*)
	0.4%	7.3%	libauto.dylib	 
Auto::MemoryScanner::scan_object_range(Auto::Range&,  
Auto::WriteBarrier*)
	3.2%	4.7%	libauto.dylib	  
Auto::MemoryScanner::scan_range(Auto::Range const&, Auto::WriteBarrier*)
	1.4%	1.4%	libauto.dyli

Re: How to ease the burden on the Garbage Collector?

2009-10-08 Thread Shawn Erickson
On Thu, Oct 8, 2009 at 7:29 AM, Gabriel Zachmann wrote:

> I'm writing a simple screensaver that is basically kind of a slide show
> screensaver.
> (So it loads many images over time, but needs to keep only 2-3 in memory at
> any given time.)
>
> I am using Core Animation for some animations on the images.
>
> I've just profiled the screensaver under 10.6 using Shark on a dual-core
> MacBookPro.
>
> It seems that about 20% of the time is spent in the Garbage Collector
> thread!


Are you sure you aren't just seeing the GC thread sitting and waiting for
something to do? What are the "hot" methods/functions you see related to the
GC thread? (many folks misread what Shark is telling them...)

-Shawn
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: How to ease the burden on the Garbage Collector?

2009-10-08 Thread Bill Bumgarner


On Oct 8, 2009, at 7:29 AM, Gabriel Zachmann wrote:

It seems that about 20% of the time is spent in the Garbage  
Collector thread!


Which is a bit surprising to me, since I don't allocate a large  
number of objects (I think) -- just a small number of large objects  
(the images).


The collector only chews CPU when there are lots of allocation events  
(and, hopefully, deallocation events) that are causing the collector  
to believe it needs to do work.   Or when something is triggering the  
collector manually really often.


Have a look at ObjectAlloc & ObjectGraph in Instruments.   That should  
give you an idea if there are lots and lots of allocation events  
occurring and, if so, what they are.  From there, it is a matter of  
minimizing the number of allocations occurring.


b.bum

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


How to ease the burden on the Garbage Collector?

2009-10-08 Thread Gabriel Zachmann
I'm writing a simple screensaver that is basically kind of a slide  
show screensaver.
(So it loads many images over time, but needs to keep only 2-3 in  
memory at any given time.)


I am using Core Animation for some animations on the images.

I've just profiled the screensaver under 10.6 using Shark on a dual- 
core MacBookPro.


It seems that about 20% of the time is spent in the Garbage Collector  
thread!


Which is a bit surprising to me, since I don't allocate a large number  
of objects (I think) -- just a small number of large objects (the  
images).


Is there anything I can do to alleviate the burden on the GC?
(The code was written under 10.5 in the reference-counted model.)

Regards,
Gabriel.



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Garbage collector related crash

2009-05-10 Thread Bill Bumgarner

On May 10, 2009, at 7:22 PM, Chris Idou wrote:
Err, why isn't that a workaround? If retaining it but not freeing it  
is a workaround, why wouldn't retaining it and freeing it after I am  
done with it work?


Because the cache will end up with with a dangling pointer that you  
can't do anything about.  As soon as the cache decides to reuse that  
slot, BOOM.


b.bum
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-10 Thread Chris Idou


Err, why isn't that a workaround? If retaining it but not freeing it is a 
workaround, why wouldn't retaining it and freeing it after I am done with it 
work?





From: Bill Bumgarner 
To: Chris Idou 
Cc: cocoa-dev@lists.apple.com
Sent: Monday, 11 May, 2009 11:59:11 AM
Subject: Re: Garbage collector related crash


On May 10, 2009, at 6:35 PM, Chris Idou wrote:
Is it fixed in a later version of Leopard, or in Snow Leopard?

Snow Leopard.

And it is a workaround to release it in the finalizer of the object that 
retains it and uses it?

No.

b.bum




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-10 Thread Bill Bumgarner

On May 10, 2009, at 6:35 PM, Chris Idou wrote:

Is it fixed in a later version of Leopard, or in Snow Leopard?


Snow Leopard.

And it is a workaround to release it in the finalizer of the object  
that retains it and uses it?


No.

b.bum

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-10 Thread Chris Idou


Is it fixed in a later version of Leopard, or in Snow Leopard?

And it is a workaround to release it in the finalizer of the object that 
retains it and uses it?





From: Bill Bumgarner 
To: Chris Idou 
Cc: cocoa-dev@lists.apple.com
Sent: Monday, 11 May, 2009 2:47:43 AM
Subject: Re: Garbage collector related crash


On May 10, 2009, at 3:47 AM, Chris Idou wrote:
When you are saying "it is broken" on Leopard, what exactly do you say you know 
is broken? GC in general, or the __strong thing, or ?

There is a bug internal the MD* API that causes this particular crash because 
it creates dangling weak references that the collecter stumbles over.   Purely 
a bug in MD* that is fixed in a later release.

b.bum



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-10 Thread Bill Bumgarner

On May 10, 2009, at 3:47 AM, Chris Idou wrote:
When you are saying "it is broken" on Leopard, what exactly do you  
say you know is broken? GC in general, or the __strong thing, or ?


There is a bug internal the MD* API that causes this particular crash  
because it creates dangling weak references that the collecter  
stumbles over.   Purely a bug in MD* that is fixed in a later release.


b.bum
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-10 Thread Chris Idou


When you are saying "it is broken" on Leopard, what exactly do you say you know 
is broken? GC in general, or the __strong thing, or ?





From: Bill Bumgarner 
To: Chris Idou 
Cc: cocoa-dev@lists.apple.com
Sent: Saturday, 9 May, 2009 3:58:11 AM
Subject: Re: Garbage collector related crash

On May 8, 2009, at 12:47 AM, Chris Idou wrote:
> I've got an object that holds onto a CF ref:
> 
> mdref= MDItemCreate(nil, (CFStringRef)path);
> [NSMakeCollectable(mdref) autorelease];
> 
> I think I'm doing the right thing in the class declaration:
> 
> 
> @interface MetadataItem : NSObject {
> __strongMDItemRefmdref;
> @end
> 
> But every now and then:
> 
> CFTypeRefres = MDItemCopyAttribute(mdref, (CFStringRef)key);
> 
> this makes it crash horribly. It's got to have something to do with garbage 
> collection, but it seems like I'm doing things right. Any thoughts?

It is broken on Leopard (and fixed in a future release);  please file a bug and 
send me the bug #.   Attach your binary to the bug with steps to reproduce.

One workaround for now -- not a very good workaround, but a workaround -- is to 
CFRetain the mdref as soon as you create it.  Then never ever CFRelease it.  
Yes, it'll leak (fortunately these are small).  But it won't crash (unless some 
other subsystem does code like yours above out of your control).

b.bum



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Garbage collector related crash

2009-05-08 Thread Bill Bumgarner

On May 8, 2009, at 12:47 AM, Chris Idou wrote:

I've got an object that holds onto a CF ref:

mdref= MDItemCreate(nil, (CFStringRef)path);
[NSMakeCollectable(mdref) autorelease];

I think I'm doing the right thing in the class declaration:


@interface MetadataItem : NSObject {
__strongMDItemRefmdref;
@end

But every now and then:

CFTypeRefres = MDItemCopyAttribute(mdref, (CFStringRef)key);

this makes it crash horribly. It's got to have something to do with  
garbage collection, but it seems like I'm doing things right. Any  
thoughts?


It is broken on Leopard (and fixed in a future release);  please file  
a bug and send me the bug #.   Attach your binary to the bug with  
steps to reproduce.


One workaround for now -- not a very good workaround, but a workaround  
-- is to CFRetain the mdref as soon as you create it.  Then never ever  
CFRelease it.  Yes, it'll leak (fortunately these are small).  But it  
won't crash (unless some other subsystem does code like yours above  
out of your control).


b.bum

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Garbage collector related crash

2009-05-08 Thread Chris Idou


I've got an object that holds onto a CF ref:

mdref= MDItemCreate(nil, (CFStringRef)path);
[NSMakeCollectable(mdref) autorelease];

I think I'm doing the right thing in the class declaration:


@interface MetadataItem : NSObject {
__strongMDItemRefmdref;
@end

But every now and then:

CFTypeRefres = MDItemCopyAttribute(mdref, (CFStringRef)key);

this makes it crash horribly. It's got to have something to do with garbage 
collection, but it seems like I'm doing things right. Any thoughts?



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Outrunning the Garbage Collector

2009-05-08 Thread Marcel Weiher

Hi Jeffrey,

I have a multithreaded application with several NSOperationQueues  
and it appears as if under heavy load conditions I'm overwhelming  
the garbage collector so-to-speak.


From what you describe, it looks like your analysis is spot on.

I essentially have three queues which can be processing different  
types of operations simultaneously.


- If I load up *one* queue with a bunch of operations and let it  
run, I find that memory is clean up very nicely. After each  
operation finishes it gets cleaned up by the collector appropriately.


- If I load up all three queues simultaneously (a not uncommon user  
scenario for this application), then I find that rarely do any of  
the operations get cleaned up. Things generally start out alright,  
but then get jugged up and very quickly the application can run out  
of memory.


You essentially have to throttle the mutator(s) so they don't outrun  
the collector.  The collector has a tough time keeping up with one  
full-throttle mutator, three (assuming you've got a thread servicing  
each queue) is fairly hopeless.  Another option *may* be to recode  
your app to produce significantly less garbage for the collector to  
clean up.


The GC release notes suggest that it's possible to "outrun" the  
collector,
http://developer.apple.com/releasenotes/Cocoa/GCReleaseNotes/ 
index.html


It is, as you've noticed.

Marcel

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Outrunning the Garbage Collector

2009-05-07 Thread Jeffrey J. Early
I have a multithreaded application with several NSOperationQueues and  
it appears as if under heavy load conditions I'm overwhelming the  
garbage collector so-to-speak.


I essentially have three queues which can be processing different  
types of operations simultaneously.


- If I load up *one* queue with a bunch of operations and let it run,  
I find that memory is clean up very nicely. After each operation  
finishes it gets cleaned up by the collector appropriately.


- If I load up all three queues simultaneously (a not uncommon user  
scenario for this application), then I find that rarely do any of the  
operations get cleaned up. Things generally start out alright, but  
then get jugged up and very quickly the application can run out of  
memory.


I've tried suspending one of the operation queues for a few seconds  
and asking the garbage collector to collect, but that didn't work.


I noticed in NSGarbageCollector.h that they say, "collects ..., but  
subject to interruption on user input". What exactly is "user input"?  
If I somehow block everything on the main thread for a short time,  
will this allow the garbage collector to collect?


The GC release notes suggest that it's possible to "outrun" the  
collector,

http://developer.apple.com/releasenotes/Cocoa/GCReleaseNotes/index.html

Thanks,
Jeffrey
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


[moderator] Re: Garbage collector vs variable lifetime

2008-06-11 Thread Scott Anguish

Folks, this is getting nowhere.

Chris Hanson (an apple engineer BTW) and Clark (and many others) have  
stated the correct answer (simply summarized below)


time to put this one to rest. there is nothing to argue about here.

scott


On Jun 11, 2008, at 8:45 AM, Clark Cox wrote:



If you're going to be returning (or accepting) more than a single  
class, you use id, which clearly communicates your intentions.


Again, no. It is perfectly acceptable to pass an NSMutableArray where
an NSArray is expected.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread j o a r


On Jun 11, 2008, at 12:29 AM, Jim Puls wrote:

For that matter, it may be worth pointing out John's confusion  
between "sloppy" and "incorrect". He makes a decent point that  
returning a mutable object when the method definition specifies an  
immutable one is sloppy and, indeed, fraught with peril.



Do you feel the same way about passing a (char *) to a method that  
takes a (const char *)?


I think that it's perfectly reasonable to expect the receiver of the  
piece of data, or object, that you hand over to respect the basic  
restrictions of that type.


j o a r


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Clark Cox
On Wed, Jun 11, 2008 at 12:01 AM, John Engelhart
<[EMAIL PROTECTED]> wrote:
>
> On Jun 10, 2008, at 11:28 AM, Charles Srstka wrote:
>>
>> I think the problem is that if NSArray has +[NSArray array] returning an
>> NSArray, then NSMutableArray has to return an NSArray also, since it can't
>> have a different method signature for the same method. As a result, if you
>> called +[NSMutableArray array], the compiler would think you were getting a
>> regular, non-mutable NSArray, and you'd get a warning if you tried to do
>> this, although the code would still work:
>
> No, each class is allowed to define different types for the same method:
>
> http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_9_section_2.html#//apple_ref/doc/uid/TP30001163-CH16-TPXREF161
>
> This whole business about '(NSArray *) means NSArray AND any of it's
> subclasses' is the result of sloppy thinking and confusing 'able to' with
> 'as per spec'.
>
> If you declare a method prototype as '-(NSArray *)resultsArray', then you
> have explicitly communicated that a NSArray is going to be returned.  Not a
> NSMutableArray. Not 'Jimmies groovy array with red pin stripes'.

This is simply not true. Returning (NSArray*) only means "I will
return an object that you can assume is an NSArray". Not a single one
of the convenience methods on NSArray actually return an NSArray, they
all return one subclass or another.

>A NSArray. Period.  A NSMutableArray != a NSArray.

No, All NSMutableArrays are also NSArrays, that is the very definition
of subclassing. In any object-oriented system, subclassing establishes
an "is-a" relationship between classes.


> If you're going to be returning (or accepting) more than a single class, you 
> use id, which clearly communicates your intentions.

Again, no. It is perfectly acceptable to pass an NSMutableArray where
an NSArray is expected.

-- 
Clark S. Cox III
[EMAIL PROTECTED]
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Charles Srstka

On Jun 11, 2008, at 2:01 AM, John Engelhart wrote:

If you declare a method prototype as '-(NSArray *)resultsArray',  
then you have explicitly communicated that a NSArray is going to be  
returned.  Not a NSMutableArray. Not 'Jimmies groovy array with red  
pin stripes'.  A NSArray. Period.  A NSMutableArray != a NSArray.   
If you're going to be returning (or accepting) more than a single  
class, you use id, which clearly communicates your intentions.


I already pointed out that there is *no such thing* as an "NSArray.  
Period." You are *never* going to get an object whose class is just  
NSArray. All that -(NSArray *)resultsArray promises is that you're  
going to get *some* kind of NSArray. An NSMutableArray == an NSArray,  
by virtue of being a subclass of it.


This is kind of a basic principle of object orientation - a method  
that returns (Foo *) could give you an object of type Foo. However, it  
could also give you any random subclass of Foo, because all those  
qualify as being a Foo, because they are subclasses. All you know  
about what you're getting is that it will provide the methods that Foo  
provides, and that you can treat it like a Foo.


A return type of NSArray * means something very explicit.  "But all  
you can expect is an object that behaves like a NSArray, so  
returning a subclass of NSArray, like NSMutableArray, is perfectly  
legal!"  You're exactly right that all I can expect is an object  
that behave like a NSArray.  /Exactly/ like a NSArray.  Not sorta.  
Not almost. Exactly.  Because that's what you explicitly stated.  So  
when the returned array mutates, either because you were sloppy and  
returned the pointer to your objects internal state, or because  
during its travels something, somewhere sends it a mutation message  
inside a @try / @catch block, I'm going to file a bug because  
whatever it is you returned did not behave like a NSArray. An / 
immutable/ array.


No, a return type of NSArray doesn't mean it can't be mutable. It  
does, however, mean that you can't *count* on it being mutable, so if  
you try to mutate it, the compiler will give you warnings (and the  
program will throw an exception if the array was not, in fact  
mutable). You also can't count on it being immutable, because no such  
promise is given.


If you are storing an array for long-term use and need it absolutely,  
positively not to mutate while you've got it, then you should be using  
-[NSArray copy] or perhaps +[NSArray arrayWithArray:] to make yourself  
a copy of it instead of just hanging onto whatever -(NSArray  
*)resultsArray gave you.


Charles
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Andy Lee

On Jun 11, 2008, at 3:01 AM, John Engelhart wrote:

-(MyObject *)copyAndCombineWith:(MyObject *)object
{
 MyObject *copy = malloc(sizeof(MyObject));
 memcpy(copy, object, sizeof(MyObject));
 copy->answer += answer;
 copy->integerRING += integerRing;
 return(copy);
}


Do not use malloc() to instantiate objects.  Do not use memcpy() to  
copy objects.


Despite looking like a C pointer, (MyObject *) is not a pointer to a  
struct; it is a reference to an object.  Do not treat objects like  
structs.


The fact that sending a subclass of the declared base class behaves  
in a nearly indistinguishable manner is the result of careful  
manipulation and subtle bending of the rules, not because it's  
literally so.


No, it's a deliberate use of the rules.  Or rather, you are making up  
rules that don't exist, and that you certainly didn't read in the docs.


Based on your misconceptions, I suspect you may also not understand  
method overriding, which is a crucial concept.


I suggest you review the docs on Objective-C, in particular:


This chapter explains how static typing works and discusses some  
other features of Objective-C


Info on method overriding, in case you need it (I may be wrong about  
that), is here:





--Andy




--Andy

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Hamish Allan
On Wed, Jun 11, 2008 at 8:01 AM, John Engelhart
<[EMAIL PROTECTED]> wrote:

> A return type of NSArray * means something very explicit.  "But all you can
> expect is an object that behaves like a NSArray, so returning a subclass of
> NSArray, like NSMutableArray, is perfectly legal!"  You're exactly right
> that all I can expect is an object that behave like a NSArray.  /Exactly/
> like a NSArray.  Not sorta. Not almost. Exactly.  Because that's what you
> explicitly stated.

What you seem to be arguing for here is a different design of the
NeXTstep classes. You want an abstract base class, NSArray, with
children NSMutableArray and NSImmutableArray. Then, if you want to
design a class to return an immutable array, you use NSImmutableArray,
and there is no room for confusion.

The designers of the NeXTstep classes presumably noticed that
NSImmutableArray wouldn't add any extra methods to NSArray, and
decided to design it the way they did. You could, if you wished, force
the issue in your own code by declaring a class NSImmutableArray
yourself.

However, this doesn't change the fact that, as the class heirarchy
stands, an NSMutableArray is an NSArray. This is a basic tenet of
polymorphism in object-oriented programming. If, from an interface
declaring (NSArray *) as its return type, you get an NSMutableArray,
don't worry -- just don't mutate it. If some other part of the
framework mutates it, this is no more correct behaviour than if it had
returned an immutable array and then overwritten some of its storage
directly in memory.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Jean-Daniel Dupas


Le 11 juin 08 à 09:01, John Engelhart a écrit :



On Jun 10, 2008, at 11:28 AM, Charles Srstka wrote:


I think the problem is that if NSArray has +[NSArray array]  
returning an NSArray, then NSMutableArray has to return an NSArray  
also, since it can't have a different method signature for the same  
method. As a result, if you called +[NSMutableArray array], the  
compiler would think you were getting a regular, non-mutable  
NSArray, and you'd get a warning if you tried to do this, although  
the code would still work:


No, each class is allowed to define different types for the same  
method:


http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_9_section_2.html#/ 
/apple_ref/doc/uid/TP30001163-CH16-TPXREF161


This whole business about '(NSArray *) means NSArray AND any of it's  
subclasses' is the result of sloppy thinking and confusing 'able to'  
with 'as per spec'.


If you declare a method prototype as '-(NSArray *)resultsArray',  
then you have explicitly communicated that a NSArray is going to be  
returned.  Not a NSMutableArray. Not 'Jimmies groovy array with red  
pin stripes'.  A NSArray. Period.  A NSMutableArray != a NSArray.   
If you're going to be returning (or accepting) more than a single  
class, you use id, which clearly communicates your intentions.


A return type of NSArray * means something very explicit.  "But all  
you can expect is an object that behaves like a NSArray, so  
returning a subclass of NSArray, like NSMutableArray, is perfectly  
legal!"  You're exactly right that all I can expect is an object  
that behave like a NSArray.  /Exactly/ like a NSArray.  Not sorta.  
Not almost. Exactly.  Because that's what you explicitly stated.  So  
when the returned array mutates, either because you were sloppy and  
returned the pointer to your objects internal state, or because  
during its travels something, somewhere sends it a mutation message  
inside a @try / @catch block, I'm going to file a bug because  
whatever it is you returned did not behave like a NSArray. An / 
immutable/ array.


You have to fill a bug againt the library that mutates the NSArray,  
not the one that create it. If a method expects an NSArray, it have to  
use it like an NSArray and not like an NSMutableArray.




smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-11 Thread Graham Cox


On 11 Jun 2008, at 5:01 pm, John Engelhart wrote:

If you declare a method prototype as '-(NSArray *)resultsArray',  
then you have explicitly communicated that a NSArray is going to be  
returned.  Not a NSMutableArray. Not 'Jimmies groovy array with red  
pin stripes'.  A NSArray. Period.  A NSMutableArray != a NSArray.   
If you're going to be returning (or accepting) more than a single  
class, you use id, which clearly communicates your intentions.




That's not the case.

A NSMutableArray is not *LIKE* an NSArray, it *IS* an NSArray - it  
implements everything that NSArray does, plus some additional stuff of  
its own, so if you return an NSMutableArray from a method returning  
NSArray*, you are not breaking any contracts. This is actually common.  
In fact, it's a key benefit/feature of *all* object-oriented  
programming. Of course you have to know that NSMutableArray is a  
subclass of NSArray, or indeed it wouldn't be correct to do this.  
However, this is clearly stated in the docs and also easily  
discoverable. There are other objects that you can't use this way -  
for example NSAttributedString is not a subclass of NSString.


id is only used in circumstances where a stronger type can't be used.  
In fact I generally avoid it except where absolutely necessary. It's  
usually used to mean unrelated classes can be substituted, or where a  
stronger type can cause access problems, as in your example of array =  
[NSMutableArray array]; Having invoked that class method, you want to  
be able to call NSMutableArray-specific methods on it. If it returned  
type NSArray*, you couldn't do so without a cast.


G.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread Jim Puls

On Jun 11, 2008, at 12:15 AM, Chris Hanson wrote:

This whole business about '(NSArray *) means NSArray AND any of  
it's subclasses' is the result of sloppy thinking and confusing  
'able to' with 'as per spec'.


No, you are wrong.  It really is "per spec."  That is an intentional  
capability in both Objective-C and C++:  You can return an instance  
of a class, or any of its subclasses, wherever an instance of that  
class is specified precisely because classes should be designed to  
be substitutable in this fashion.  This is the essence of  
polymorphism in object-oriented programming and is summarized by the  
Liskov substitution principle.



For that matter, it may be worth pointing out John's confusion between  
"sloppy" and "incorrect". He makes a decent point that returning a  
mutable object when the method definition specifies an immutable one  
is sloppy and, indeed, fraught with peril.


But Chris is still correct that doing so is completely allowable, at  
least under the true-in-Cocoa assumption that the mutable data types  
are implemented as subclasses of the immutable ones.


-> jp



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-11 Thread Chris Hanson

On Jun 11, 2008, at 12:01 AM, John Engelhart wrote:

This whole business about '(NSArray *) means NSArray AND any of it's  
subclasses' is the result of sloppy thinking and confusing 'able to'  
with 'as per spec'.


No, you are wrong.  It really is "per spec."  That is an intentional  
capability in both Objective-C and C++:  You can return an instance of  
a class, or any of its subclasses, wherever an instance of that class  
is specified precisely because classes should be designed to be  
substitutable in this fashion.  This is the essence of polymorphism in  
object-oriented programming and is summarized by the Liskov  
substitution principle.


Languages like Smalltalk and Ruby take this even further with "duck  
typing," where they lack type declaration entirely and an object's  
interface is defined entirely by its expected behavior.


If you declare a method prototype as '-(NSArray *)resultsArray',  
then you have explicitly communicated that a NSArray is going to be  
returned.  Not a NSMutableArray. Not 'Jimmies groovy array with red  
pin stripes'.  A NSArray. Period.  A NSMutableArray != a NSArray.   
If you're going to be returning (or accepting) more than a single  
class, you use id, which clearly communicates your intentions.


This is absolutely, categorically incorrect.

The Objective-C language, for the purposes of type checking, treats  
assignment, passing and return of subclasses as equivalent to the  
assignment, passing and return of superclasses.


It does so specifically so instances of a subclass may be assigned,  
passed and returned wherever an instance of a superclass is required.


A return type of NSArray * means something very explicit.  "But all  
you can expect is an object that behaves like a NSArray, so  
returning a subclass of NSArray, like NSMutableArray, is perfectly  
legal!"  You're exactly right that all I can expect is an object  
that behave like a NSArray.  /Exactly/ like a NSArray.  Not sorta.  
Not almost. Exactly.  Because that's what you explicitly stated.


You are incorrect.  It means all you can expect is an object that  
obeys NSArray's API contract.  Note that it has been pointed out, at  
LEAST once in this thread, that you will NEVER receive an actual  
NSArray because NSArray is actually a class cluster.






You keep insisting that Objective-C is designed in and behaves in a  
way in which it simply does not.  Please stop.


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-11 Thread John Engelhart


On Jun 10, 2008, at 11:28 AM, Charles Srstka wrote:


I think the problem is that if NSArray has +[NSArray array]  
returning an NSArray, then NSMutableArray has to return an NSArray  
also, since it can't have a different method signature for the same  
method. As a result, if you called +[NSMutableArray array], the  
compiler would think you were getting a regular, non-mutable  
NSArray, and you'd get a warning if you tried to do this, although  
the code would still work:


No, each class is allowed to define different types for the same method:

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_9_section_2.html#/ 
/apple_ref/doc/uid/TP30001163-CH16-TPXREF161


This whole business about '(NSArray *) means NSArray AND any of it's  
subclasses' is the result of sloppy thinking and confusing 'able to'  
with 'as per spec'.


If you declare a method prototype as '-(NSArray *)resultsArray', then  
you have explicitly communicated that a NSArray is going to be  
returned.  Not a NSMutableArray. Not 'Jimmies groovy array with red  
pin stripes'.  A NSArray. Period.  A NSMutableArray != a NSArray.  If  
you're going to be returning (or accepting) more than a single class,  
you use id, which clearly communicates your intentions.


A return type of NSArray * means something very explicit.  "But all  
you can expect is an object that behaves like a NSArray, so returning  
a subclass of NSArray, like NSMutableArray, is perfectly legal!"   
You're exactly right that all I can expect is an object that behave  
like a NSArray.  /Exactly/ like a NSArray.  Not sorta. Not almost.  
Exactly.  Because that's what you explicitly stated.  So when the  
returned array mutates, either because you were sloppy and returned  
the pointer to your objects internal state, or because during its  
travels something, somewhere sends it a mutation message inside a  
@try / @catch block, I'm going to file a bug because whatever it is  
you returned did not behave like a NSArray. An /immutable/ array.


Consider the following:

@interface MyObject : NSObject {
  double answer;
  int integerRing;
}
-(MyObject *)copyAndCombineWith:(MyObject *)object;
@end


-(MyObject *)copyAndCombineWith:(MyObject *)object
{
  MyObject *copy = malloc(sizeof(MyObject));
  memcpy(copy, object, sizeof(MyObject));
  copy->answer += answer;
  copy->integerRING += integerRing;
  return(copy);
}

Then you make a subclass:

@interface ASubclass : MyObject {
  NSArray *stuff;
  NSView *view;
}
@end

You inevitably do something like:

@interface ASubclass

-(void)doSomething {
  ASubclass *copy = [otherMyObject copyAndCombineWith:self];
}
@end

And things very obviously do not work.  The reason is that doSomething  
assumes that the declaration of copyAndCombineWith:(MyObject *)object  
means "and any subclass".  It doesn't.  It means "MyObject *".  I knew  
that when I wrote it.  I was quite explicit with the prototype.  The  
compiler obviously knew /exactly/ what I meant.  The final clue is the  
error returned for the obvious misspelling:


test.m: In function '-[MyObject copyAndCombineWith:]':
test.m:24: error: 'struct MyObject' has no member named 'integerRING'

Statically typing a class in a prototype doesn't mean "and any  
subclass".  It never did.  The 'struct MyObject' is the tell tale  
evidence that it's not even possible for MyObject * to mean "and any  
subclass".  When you statically type the class you mean it literally.   
The fact that sending a subclass of the declared base class behaves in  
a nearly indistinguishable manner is the result of careful  
manipulation and subtle bending of the rules, not because it's  
literally so.  No amount of insisting that the illusion is real will  
ever turn it in to fact.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-10 Thread Hamish Allan
On Tue, Jun 10, 2008 at 4:28 PM, Charles Srstka
<[EMAIL PROTECTED]> wrote:

> I think the problem is that if NSArray has +[NSArray array] returning an
> NSArray, then NSMutableArray has to return an NSArray also, since it can't
> have a different method signature for the same method. As a result, if you
> called +[NSMutableArray array], the compiler would think you were getting a
> regular, non-mutable NSArray, and you'd get a warning if you tried to do
> this, although the code would still work:
>
> NSMutableArray *array = [NSMutableArray array];

Ah, yes, so you would. I see!

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-10 Thread Adam R. Maxwell
 
On Tuesday, June 10, 2008, at 08:29AM, "Charles Srstka" <[EMAIL PROTECTED]> 
wrote:
>On Jun 9, 2008, at 5:55 PM, Hamish Allan wrote:
>
>> Sure. But it gives you *more* information than if it just returns
>> "id". I agree with you in all other respects of your post, but I don't
>> agree that +[NSArray array] returns "id" because if it returned
>> "NSArray *" you'd have to have a separate declaration for
>> +[NSMutableArray array]. Indeed, that line of reasoning leads to
>> John's way of thinking: that if you return something more specific
>> than "id", it is in some sense indicative that the returned object is
>> more likely to be of a specific class, rather than a subclass thereof.
>
>I think the problem is that if NSArray has +[NSArray array] returning  
>an NSArray, then NSMutableArray has to return an NSArray also, since  
>it can't have a different method signature for the same method. As a  
>result, if you called +[NSMutableArray array], the compiler would  
>think you were getting a regular, non-mutable NSArray, and you'd get a  
>warning if you tried to do this, although the code would still work:

I'm not sure if I follow you, but the trivial example below compiles with only 
one warning.  NSMutableArray could redeclare the superclass' implementation of 
+array, but that would have to be done for each factory method that presently 
returns an id, which is pretty annoying.  In addition, each successive subclass 
has to redeclare /and/ reimplement all of the factory methods.  Another 
example: if you subclass NSFontManager using setFontManagerFactory:, every time 
you call +sharedFontManager you have to cast to your subclass since it's 
strongly typed.

#import 

@interface Thing : NSObject
+ (Thing *)thing;
@end

@interface MutableThing : Thing
+ (MutableThing *)thing;
@end

@implementation Thing
+ (Thing *)thing { return [NSAllocateObject(self, 0, NULL) autorelease]; }
@end

@implementation MutableThing
+ (MutableThing *)thing { return [NSAllocateObject(self, 0, NULL) autorelease]; 
}
@end

int main (int argc, char const *argv[])
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];

Thing *a = [Thing thing];
a = [MutableThing thing];

MutableThing *b = [MutableThing thing];   

// warning: assignment from distinct Objective-C type
b = [Thing thing];

[pool release];
return 0;
} 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-10 Thread Charles Srstka

On Jun 9, 2008, at 5:55 PM, Hamish Allan wrote:


Sure. But it gives you *more* information than if it just returns
"id". I agree with you in all other respects of your post, but I don't
agree that +[NSArray array] returns "id" because if it returned
"NSArray *" you'd have to have a separate declaration for
+[NSMutableArray array]. Indeed, that line of reasoning leads to
John's way of thinking: that if you return something more specific
than "id", it is in some sense indicative that the returned object is
more likely to be of a specific class, rather than a subclass thereof.


I think the problem is that if NSArray has +[NSArray array] returning  
an NSArray, then NSMutableArray has to return an NSArray also, since  
it can't have a different method signature for the same method. As a  
result, if you called +[NSMutableArray array], the compiler would  
think you were getting a regular, non-mutable NSArray, and you'd get a  
warning if you tried to do this, although the code would still work:


NSMutableArray *array = [NSMutableArray array];

The only way to get the compiler warnings to shut up would be to cast  
it. If the methods return id, then the compiler just assumes you're  
doing the right thing (which also means you can do stupid things like  
assign +[NSMutableArray array] to an NSString or something which would  
of course end up blowing up before too long, so it's not perfect  
either, but it's certainly less annoying than having to typecast every  
assignment of a newly-initialized NSMutableArray).


Charles
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-10 Thread Charles Srstka

On Jun 9, 2008, at 1:39 PM, Chris Hanson wrote:

It is perfectly legal to return an NSMutableArray from a  
hypothetical +(NSArray *)array method.


However, all the sender of that +(NSArray *)array message can know  
is that the result can be treated as an NSArray.  It can't know  
whether an NSArray or NSMutableArray is returned (unless it does  
extra work, like using -isKindOfClass:, which also happens to be  
fragile).


Even isKindOfClass: won't work in this case, because NSArray and  
NSMutableArray both usually end up being the same class, NSCFArray.  
This class seems to be a subclass of NSMutableArray, and using  
isKindOfClass: on it will always return YES for NSMutableArray, even  
if it's not actually mutable.


I don't really know of any way to actually test whether an NSArray is  
mutable or not programatically (well, I suppose you could try mutating  
it and see if you catch an exception or not, but that's obviously not  
a very good solution).


Charles
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Hamish Allan
On Mon, Jun 9, 2008 at 7:39 PM, Chris Hanson <[EMAIL PROTECTED]> wrote:

> It is perfectly legal to return an NSMutableArray from a hypothetical
> +(NSArray *)array method.
>
> However, all the sender of that +(NSArray *)array message can know is that
> the result can be treated as an NSArray.  It can't know whether an NSArray
> or NSMutableArray is returned (unless it does extra work, like using
> -isKindOfClass:, which also happens to be fragile).

Sure. But it gives you *more* information than if it just returns
"id". I agree with you in all other respects of your post, but I don't
agree that +[NSArray array] returns "id" because if it returned
"NSArray *" you'd have to have a separate declaration for
+[NSMutableArray array]. Indeed, that line of reasoning leads to
John's way of thinking: that if you return something more specific
than "id", it is in some sense indicative that the returned object is
more likely to be of a specific class, rather than a subclass thereof.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Chris Hanson

On Jun 9, 2008, at 11:17 AM, Hamish Allan wrote:


On Mon, Jun 9, 2008 at 7:02 PM, Chris Hanson <[EMAIL PROTECTED]> wrote:

The reason these kinds of methods have a return type of (id) is  
that there
is no way to say "returns an object of the receiver's class."  For  
example,
+[NSArray array] returns (id) rather than (NSArray *) because  
otherwise
+[NSMutableArray array] would require a separate declaration  
(NSMutableArray
*).  Rather than have a large number of separate declarations,  
these methods

return (id).


If this is true, it rather contradicts your point, because it should
be perfectly legal to return an NSMutableArray (a subclass of NSArray)
from +(NSArray *)array.


It is perfectly legal to return an NSMutableArray from a hypothetical + 
(NSArray *)array method.


However, all the sender of that +(NSArray *)array message can know is  
that the result can be treated as an NSArray.  It can't know whether  
an NSArray or NSMutableArray is returned (unless it does extra work,  
like using -isKindOfClass:, which also happens to be fragile).


This is actually used quite often in Cocoa development.  For example,  
if you have an Account class with a "transactions" array property that  
you want to use with Key-Value Observing, you'll probably write its  
interface to look something like this (if you implement all of the  
various KVO methods):


  @interface Account : NSObject {
  NSMutableArray *transactions;
  }

  - (NSArray *)transactions;
  - (void)setTransactions:(NSArray *)newTransactions;

  - (void)insertObject:(id)object inTransactionsAtIndex: 
(NSUInteger)index;

  - (void)removeObjectFromTransactionsAtIndex:(NSUInteger)index;

  @end

All of these methods would actually be implemented to return or  
manipulate the NSMutableArray instance variable.


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Hamish Allan
On Mon, Jun 9, 2008 at 7:02 PM, Chris Hanson <[EMAIL PROTECTED]> wrote:

> The reason these kinds of methods have a return type of (id) is that there
> is no way to say "returns an object of the receiver's class."  For example,
> +[NSArray array] returns (id) rather than (NSArray *) because otherwise
> +[NSMutableArray array] would require a separate declaration (NSMutableArray
> *).  Rather than have a large number of separate declarations, these methods
> return (id).

If this is true, it rather contradicts your point, because it should
be perfectly legal to return an NSMutableArray (a subclass of NSArray)
from +(NSArray *)array.

Notwithstanding, you are right that John seems to be mistaken about
polymorphism. John, perhaps it would help you to think of 'id' as
being the type of an abstract superclass to NSObject? (Yes, I know
from previous discussions that 'id' is actually a typedef of a struct,
etc. Let's not revisit that!)

If I ever claimed that the GC's behaviour is wrong, let me rescind
that: it was based on my conflation of "the stack" and "the current
scope". However, I do still think that a whole class of bugs could
easily be avoided by having the compiler ensure that pointer variables
remain on the stack whilst they are in scope, and I'm not convinced
that the cost of the extra pointer copy and stack slot this would
require is such a terrible a price to pay.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Chris Hanson

On Jun 9, 2008, at 10:24 AM, John Engelhart wrote:

This is not a bug.  This is fundamental to how object-oriented  
programming works!  You should always be able to pass an instance  
of a subclass wherever an instance of the superclass is expected.


You're mistaken.  You have statically typed the object.


John, it is you who are mistaken.  You're mistaken about what  
"statically typed" means in Objective-C.  It does not mean "I will  
always pass an instance of exactly NSArray", it means "I will always  
pass an instance of NSArray or a subclass."


That's all it means.

Just as '+(NSArray *)array' does not mean "and any possible  
subclasses"


In fact, it WOULD mean that.  It means "returns an instance of  
NSArray, or any subclass thereof, that senders should treat as an  
NSArray."


For example, if -[NSArray array] were declared as above, it could  
still perfectly validly return a shared instance of a special  
_NSEmptyArray subclass of NSArray.


All your code will know or care about is that what it gets back is  
usable as an NSArray.


If one applies the 'attribute only applies to the class it was  
specified for' rule:


By statically typing the class to NSArray, you have certified to  
the compiler that no other object type will be received as an  
argument.  When you passed it an object of a different type, even  
a subclass, you broke your promise to the compiler.


This is simply wrong.


You're encouraged to read the section "Enabling Static Behavior -  
Static Typing" in the Objective-C manual.  This is what allows for  
subclasses to return different types for the same method.  By  
statically typing a declaration as NSArray, you've told the compiler  
that the object is a NSArray (only) class object, and only the  
methods for NSArray apply.


John, with all due respect, I do know what I'm talking about here --  
I've been working with Objective-C on NeXT and Mac OS X for 11 years  
now -- and it is you who are wrong about this.


Whether you're dealing with Objective-C, C++, or Java, instances of  
subclasses are always substitutable for instances of their superclass  
where the type system is concerned.


The fact that object instantiation methods return 'id' and not the  
base class are further evidence that this is indeed the case.


The reason these kinds of methods have a return type of (id) is that  
there is no way to say "returns an object of the receiver's class."   
For example, +[NSArray array] returns (id) rather than (NSArray *)  
because otherwise +[NSMutableArray array] would require a separate  
declaration (NSMutableArray *).  Rather than have a large number of  
separate declarations, these methods return (id).


You also can't send messages declared in a subclass of NSArray to a  
'NSArray *array;' object without getting a warning.  Again, further  
evidence that the compiler believes that only the explicitly named  
class is applicable, and not 'any and all subclasses'.


You misunderstand.  You can *assign* an instance of any subclass to a  
variable typed as a class.  The compiler will warn you about any  
messages you send that aren't in the interface of the typed class,  
however.


Thus you can say, perfectly validly:

  NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
  NSArray *array = mutableArray;

This is perfectly fine.  However, the compiler will give you a warning  
if you try to send any non-NSArray messages to "array."


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread John Engelhart


On Jun 9, 2008, at 6:51 AM, Chris Hanson wrote:


On Jun 9, 2008, at 12:56 AM, John Engelhart wrote:

The semantics are preserved and identical results are calculated  
(the 'meaning' is the same).  The semantics do not require square()  
to literally be called each time.


Yes, that is very clear, because the compiler can have full  
knowledge that


In the same sense, there is no requirement that a message literally  
be sent each time it appears in the source code as long as it can  
be shown that the results would be identical.


This is where you're incorrect.  A message MUST be sent, literally,  
each time it appears in the source code.  Under the Objective-C  
semantics it CANNOT be shown at compile time that the results of  
"the same" message send will be identical.


Yes, and "under the semantics of ANSI C it CANNOT be show at compile  
time that the results of the same C library function call in  
succession will be identical".


The const and pure attributes tell the compiler 'but in this case,  
despite what the rules strictly say, I'm saying that it doesn't apply  
in this particular case.'  By adding the attribute to a functions  
prototype, you take responsibility for the problems it may cause if at  
some later point this turns out to not be true, like say linking to a  
different version of a C library.


This isn't rocket science.  There ARE risks to overriding the  
conservative, guaranteed to work defaults.  You CAN break things, even  
when this feature is limited to just plain C.  If a newer version of a  
library invalidates the requirements of the attributes as they were  
declared for its prototype, yes, you're probably going to have some  
serious breakage.  And yet the last time you fired up the compiler, it  
cranked out code that could, just maybe, break with some future  
version of libSystem.




For an extreme example, you can replace method definitions at run- 
time.  This is done in real, production code; it's not hypothetical.


You've missed an important point: "as long as it can be shown that the  
results would be identical.".  If you change things in such a way that  
the results would no longer be identical, then yes, a message would  
have to be sent each time.


Strictly speaking, under Objective-C semantics, it CANNOT be shown  
that a message to an object will return a result of the type indicated  
by its compile time prototype.  Or that the argument types accepted  
indicated by the prototype remain the same as those that are  
ultimately accepted at run time.


If I declare a method

-(id)mySuperMethod __attribute((const));

And then you choose to swap out the code for my method that violates  
the prototypes attribute, why is this the fault of  
__attribute((const))?  I, the author of mySuperMethod have certified  
via my prototype that __attribute((const)) applies to the code that I  
wrote, and it returns a type of id.  You can not just swap and swizzle  
things without any regard for the original prototype.  Otherwise I'm  
free to swizzle in a chunk of code that returns a double and complain  
that it's not my fault.




The run time dynamic dispatch nature of objc makes such 'inter- 
message dispatch optimizations' much, much harder, especially at  
compile time.  Ultimately, though, they are fundamentally the same  
in terms of optimization.


No, really, they aren't.  They are fundamentally different because  
you cannot know, from one Planck-time tick of the Universe's clock  
to the next, whether such an optimization is possible.  (I hope you  
don't mind if I also indulge in a bit of hyperbole...)


For example, a whole-program JIT optimizer could theoretically  
generate some code that inlines a message dispatch, or even  
eliminates it entirely, but it can't change the semantics of the  
surrounding code based on the fact that it has done so.  (Which is  
what eliminating the second [data self]; would do.)  Essentially, it  
must preserve knowledge that an invocation of [self data] MIGHT be  
present at that effective location, because it MIGHT actually have  
to invoke it after all if a method is swizzled, a category is  
loaded, and so on.


Such a theoretical JIT compiler would have all the information  
required to successfully determine if removing the sending of the  
message 'self' to object 'data' would alter the meaning of the code.


If the JIT compiler can successfully reason that the whole process of  
dispatching the 'self' message to 'data' results in no side effects  
and alters no global state, then it follows it can remove the  
statement without changing the meaning (the semantics) of the code.


If it can be shown that removing a line of code can not possibly alter  
the meaning, effects, global state, or results of code in question,  
then by definition the JIT compiler can remove '[data self]' without  
altering the semantics of what was written since it has proven that  
executing that line of code or not executing that li

Re: Garbage collector vs variable lifetime

2008-06-09 Thread Charles Srstka

On Jun 9, 2008, at 2:56 AM, John Engelhart wrote:

Well, in the case of your example, you have a bug: You have  
statically typed the class to NSArray, not your subclass.  If one  
applies the 'attribute only applies to the class it was specified  
for' rule:


By statically typing the class to NSArray, you have certified to the  
compiler that no other object type will be received as an argument.   
When you passed it an object of a different type, even a subclass,  
you broke your promise to the compiler.


What on earth are you talking about? When you're working with  
NSArrays, you're *always* dealing with a subclass. You will *never*  
have an object that's just of class NSArray, because NSArray is a  
class cluster. When you initialize an NSArray, Foundation gives you  
whatever subclass of NSArray it figures is most suitable for whatever  
you're doing. This is even mentioned in the documentation for NSArray.


Let me show you an example:

#import 

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSArray *array = [NSArray arrayWithObjects:@"foo", @"bar", nil];

NSLog(@"array is an %@", NSStringFromClass([array class]));

[pool drain];
return 0;
}

When run, this gives:

[Session started at 2008-06-09 11:22:30 -0500.]
2008-06-09 11:22:30.641 test[14449:10b] array is an NSCFArray

The Debugger has exited with status 0.

As you see, what I have is an instance of NSCFArray (a private  
subclass for which we have no headers), even though I initialized an  
NSArray. This happens with a lot of other Foundation objects too, like  
NSString (get yourself one of those, and you could end up with a  
NSConstantString, an NSCFString, an NSPathStore2, or who knows what  
else. The only guarantee you have is that the object will provide all  
the methods that the abstract superclass promises, but which  
particular subclass you're getting and what's under the hood, you  
can't know. Heck, the situation might even change, so that the NSArray  
or NSString subclass you get might be different in a later version of  
OS X than it is currently in 10.5.3. Class clusters are extremely  
common in the default Cocoa classes, and are a fairly common practice  
in general with Cocoa programming (my app, for one, uses class  
clusters).  So there's certainly no way a compiler should be able to  
tell what particular subclass of NSArray (or perhaps even a custom  
subclass that you defined) it's got just from looking at an NSArray,  
and certainly no one's promised any such thing to the compiler.


Charles
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Antonio Nunes

On 9 Jun 2008, at 00:53, Chris Kane wrote:


On 7 Jun 2008, at 09:07, Antonio Nunes wrote:

On 7 Jun 2008, at 06:16, Ken Thomases wrote:

The issue is, how can one know when this technique is necessary?


By proper documentation. As Bill mentioned earlier, the  
documentation needs to mention this behaviour. Just as retain/ 
release, GC has its own caveats, it's own moments where one has to  
take special care. This appears to be one of them. If I read Bill's  
explanation correctly then once the documentation gets updated and  
distributed anyone can know when this technique is necessary (as  
long as they know what they're doing, which goes for anything in  
programming).


Oh, yes, it's just that simple.  Even  
understanding the potential does not necessarily lead to recognizing  
when special action needs to be taken. In amongst the hundred other  
things you have to keep in mind as you write a method, there will  
also be, "let's see, is this the last use of this object in this 100- 
line method? Hmm, yes, it appears so.  Let's  
see, do I need to take any special actions ...? OK, now what about  
this next object ...?" etc.  And what about code which already  
exists, such as "millions" of lines of Cocoa/ObjC code in the OS  
frameworks?  Somebody has gone over years of accummulated  
"optimized" code with a fine-tooth comb to find such things?  I'll  
say no more; these are just hypothetical statements pointing out the  
shallowness of a "documentation bandaid" approach.


The question was: How _can_ one know: Having this documented enables  
people to know this is something to be on the lookout for. Of course  
the fact that something is documented doesn't imply that we won't miss  
these caveats. We make mistakes all over the place. But we can't look  
out for what we don't know. So let me put it like this: documentation  
is the first step.


(By the way, and because of the recent flames against Apple's  
documentation: I think Apple are doing a great job, and constantly  
trying to improve upon what they have to offer.)


It'd be much better if the tools could warn you about such things in  
the source code.  Or something.


That would indeed be most useful. Or something ;-)

António

---
Some things have to be believed to be seen.

--Ralph Hodgson
---



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Chris Hanson

On Jun 9, 2008, at 12:56 AM, John Engelhart wrote:

The semantics are preserved and identical results are calculated  
(the 'meaning' is the same).  The semantics do not require square()  
to literally be called each time.


Yes, that is very clear, because the compiler can have full knowledge  
that


In the same sense, there is no requirement that a message literally  
be sent each time it appears in the source code as long as it can be  
shown that the results would be identical.


This is where you're incorrect.  A message MUST be sent, literally,  
each time it appears in the source code.  Under the Objective-C  
semantics it CANNOT be shown at compile time that the results of "the  
same" message send will be identical.


For an extreme example, you can replace method definitions at run- 
time.  This is done in real, production code; it's not hypothetical.


The run time dynamic dispatch nature of objc makes such 'inter- 
message dispatch optimizations' much, much harder, especially at  
compile time.  Ultimately, though, they are fundamentally the same  
in terms of optimization.


No, really, they aren't.  They are fundamentally different because you  
cannot know, from one Planck-time tick of the Universe's clock to the  
next, whether such an optimization is possible.  (I hope you don't  
mind if I also indulge in a bit of hyperbole...)


For example, a whole-program JIT optimizer could theoretically  
generate some code that inlines a message dispatch, or even eliminates  
it entirely, but it can't change the semantics of the surrounding code  
based on the fact that it has done so.  (Which is what eliminating the  
second [data self]; would do.)  Essentially, it must preserve  
knowledge that an invocation of [self data] MIGHT be present at that  
effective location, because it MIGHT actually have to invoke it after  
all if a method is swizzled, a category is loaded, and so on.



If I write

- (void)doSomething:(NSArray *)array {
   NSUInteger count1 = [array count];
   NSUInteger count2 = [array count];
   NSLog(@"%u", count1);
   NSLog(@"%u", count2);
}

the compiler can't collapse those into a single invocation of - 
count.  After all, it could be passed a subclass of NSArray for  
whom -count has side-effects.  Think about a "thread-safe  
array" (as bad as the concept might be) for example.


Well, in the case of your example, you have a bug: You have  
statically typed the class to NSArray, not your subclass.


This is not a bug.  This is fundamental to how object-oriented  
programming works!  You should always be able to pass an instance of a  
subclass wherever an instance of the superclass is expected.


 If one applies the 'attribute only applies to the class it was  
specified for' rule:


By statically typing the class to NSArray, you have certified to the  
compiler that no other object type will be received as an argument.   
When you passed it an object of a different type, even a subclass,  
you broke your promise to the compiler.


This is simply wrong.

  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Chris Hanson

On Jun 8, 2008, at 10:03 PM, John Engelhart wrote:

The result from [data self] is invariant, it does not matter if it  
is executed immediately after the object is instantiated or just  
before [data release], the result is always the same.


There is no way in the Objective-C language as it currently stands  
that the compiler can make that assumption.


Since -(id)self causes no side effects, and the result of which is  
presumably unused in our hypothetical example, the statement  
accomplishes no real work and can be eliminated.


The compiler has no intimate knowledge of what the -self message  
actually represents, and *cannot* make that optimization, without  
substantial extension to the semantics of Objective-C.


The compiler -- as it currently is -- MUST emit a call to one of the  
objc_msgSend* functions for EVERY message expression it sees, without  
re-ordering them, due to the semantics of the language.


If Objective-C *is* ever extended to support a construct like  
__attribute__((const)) on methods, it must do so in a way that is both  
binary- and source-compatible with existing code.  Hence you're taking  
a purely-hypothetical language construct and extrapolating a problem  
that wouldn't be allowed due to


Use of interior pointers in a garbage collected system is hard to get  
right, especially when the garbage collection is concurrent/threaded.   
That doesn't mean, however, that Objective-C garbage collection in  
Leopard is inherently flawed or that it should be avoided:  It works  
quite well both theoretically and in practice, and it supports the  
development of large and well-performing applications.


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-09 Thread Jean-Daniel Dupas


Le 9 juin 08 à 09:56, John Engelhart a écrit :



On Jun 8, 2008, at 11:48 PM, Chris Hanson wrote:


On Jun 8, 2008, at 5:39 PM, John Engelhart wrote:


On Jun 7, 2008, at 7:11 PM, Chris Hanson wrote:

This won't happen because each message expression -- just as with  
function-call expressions -- is a sequence point.  The compiler  
can't know what side-effects [data self] might have, so it can't  
re-order the invocation to elsewhere.


This is not necessarily true.  If the const and pure GCC  
__attribute(())s were extended to objc methods then the compiler  
would be free to perform common subexpression and loop invariant  
code movement optimizations.


They can't be, while preserving the existing semantics of the  
language.  In the existing semantics, a message send always results  
in a dynamic dispatch.


This is true for C as well.  The semantics of the C language are  
such that a function being called in the source always results in  
one function call during execution.


Then consider the case of:

int square(int x) { return(x*x); }

int something(int y) {
int r = 0;
for(int z = 0; z < 25; z++) { r += square(y); }
return(r);
}

An inter-procedural optimizing compiler will eliminate the function  
call to square and replace it with (y*y).  It will also determine  
that (y*y) is loop invariant and hoist it out of the loop body.


The semantics are preserved and identical results are calculated  
(the 'meaning' is the same).  The semantics do not require square()  
to literally be called each time.  In the same sense, there is no  
requirement that a message literally be sent each time it appears in  
the source code as long as it can be shown that the results would be  
identical.  Identical results implies identical meaning, which in  
turn means semantics are preserved.


In the case of [data self], this essentially becomes the function:

id self(id self, SEL _cmd) { return(self); }


How do you know at compile time that that will always be the case ?  
How do you know that their will not have some categorie that override  
self and change the implementation ? Even without category, it's  
perfectly possible to change the implementation pointer of the Method  
self using runtime functions.



A sufficiently aware optimizing compiler (think every single line of  
source for everything as one multi-gigabyte translation unit) could  
hypothetically trace message dispatches such that it could eliminate  
the intermediate dynamic dispatch and be left with just the  
function, such as:


{ NSData *data = /* valid ptr */; /* do some work */ self(data,  
"self");  self(data, "self"); }


The compiler would be free to eliminate both function calls.   
Semantics would be wholly preserved: The self function causes no  
program visible state changes, therefore by definition its  
execution, or lack of execution, can not have an effect.


The run time dynamic dispatch nature of objc makes such 'inter- 
message dispatch optimizations' much, much harder, especially at  
compile time.  Ultimately, though, they are fundamentally the same  
in terms of optimization.





The 'self' message would definitely fall under the domain of these  
attributes, thus the original argument is apropos.


For source compatibility, you almost certainly could *not* suddenly  
indicate that "[foo self]; [foo self];" results in only one  
invocation of -self by the compiler, at least for subclasses of  
NSObject or NSProxy.


After all, a subclass of NSObject may have overridden -self to do  
something else, and the compilation unit containing the above two  
invocations may have no idea what the class of "foo" is with which  
to make that judgment.


Nonsense.  Look, these kinds of attributes are a lot like  
typecasting.  You can typecast away const, volatile, or whatever and  
even stuff a short in to a pointer and vice versa.  That doesn't  
make it right.  The typecast overrides the compilers safeties, you  
essentially certify that your typecasted result is true and correct  
despite what the rules say.  If you end up shooting yourself in the  
foot, you only have yourself to blame.


Besides, it's not that hard to come up with some simple additions  
for when an attribute like 'const' or 'pure' can legitimately be  
applied by the compiler within the context of objc objects.  An  
obvious one would be that the attribute only applies to the class it  
was declared for and nothing else, even subclasses.




Obvious candidates are immutable objects 'length', 'count', etc,  
which would result in a pretty big win if these attributes were  
available.


If I write

- (void)doSomething:(NSArray *)array {
   NSUInteger count1 = [array count];
   NSUInteger count2 = [array count];
   NSLog(@"%u", count1);
   NSLog(@"%u", count2);
}

the compiler can't collapse those into a single invocation of - 
count.  After all, it could be passed a subclass of NSArray for  
whom -count has side-effects.  Think about a "thread-safe  
array" (

Re: Garbage collector vs variable lifetime

2008-06-09 Thread John Engelhart


On Jun 8, 2008, at 11:48 PM, Chris Hanson wrote:


On Jun 8, 2008, at 5:39 PM, John Engelhart wrote:


On Jun 7, 2008, at 7:11 PM, Chris Hanson wrote:

This won't happen because each message expression -- just as with  
function-call expressions -- is a sequence point.  The compiler  
can't know what side-effects [data self] might have, so it can't  
re-order the invocation to elsewhere.


This is not necessarily true.  If the const and pure GCC  
__attribute(())s were extended to objc methods then the compiler  
would be free to perform common subexpression and loop invariant  
code movement optimizations.


They can't be, while preserving the existing semantics of the  
language.  In the existing semantics, a message send always results  
in a dynamic dispatch.


This is true for C as well.  The semantics of the C language are such  
that a function being called in the source always results in one  
function call during execution.


Then consider the case of:

int square(int x) { return(x*x); }

int something(int y) {
 int r = 0;
 for(int z = 0; z < 25; z++) { r += square(y); }
 return(r);
}

An inter-procedural optimizing compiler will eliminate the function  
call to square and replace it with (y*y).  It will also determine that  
(y*y) is loop invariant and hoist it out of the loop body.


The semantics are preserved and identical results are calculated (the  
'meaning' is the same).  The semantics do not require square() to  
literally be called each time.  In the same sense, there is no  
requirement that a message literally be sent each time it appears in  
the source code as long as it can be shown that the results would be  
identical.  Identical results implies identical meaning, which in turn  
means semantics are preserved.


In the case of [data self], this essentially becomes the function:

id self(id self, SEL _cmd) { return(self); }

A sufficiently aware optimizing compiler (think every single line of  
source for everything as one multi-gigabyte translation unit) could  
hypothetically trace message dispatches such that it could eliminate  
the intermediate dynamic dispatch and be left with just the function,  
such as:


{ NSData *data = /* valid ptr */; /* do some work */ self(data,  
"self");  self(data, "self"); }


The compiler would be free to eliminate both function calls.   
Semantics would be wholly preserved: The self function causes no  
program visible state changes, therefore by definition its execution,  
or lack of execution, can not have an effect.


The run time dynamic dispatch nature of objc makes such 'inter-message  
dispatch optimizations' much, much harder, especially at compile  
time.  Ultimately, though, they are fundamentally the same in terms of  
optimization.





The 'self' message would definitely fall under the domain of these  
attributes, thus the original argument is apropos.


For source compatibility, you almost certainly could *not* suddenly  
indicate that "[foo self]; [foo self];" results in only one  
invocation of -self by the compiler, at least for subclasses of  
NSObject or NSProxy.


After all, a subclass of NSObject may have overridden -self to do  
something else, and the compilation unit containing the above two  
invocations may have no idea what the class of "foo" is with which  
to make that judgment.


Nonsense.  Look, these kinds of attributes are a lot like  
typecasting.  You can typecast away const, volatile, or whatever and  
even stuff a short in to a pointer and vice versa.  That doesn't make  
it right.  The typecast overrides the compilers safeties, you  
essentially certify that your typecasted result is true and correct  
despite what the rules say.  If you end up shooting yourself in the  
foot, you only have yourself to blame.


Besides, it's not that hard to come up with some simple additions for  
when an attribute like 'const' or 'pure' can legitimately be applied  
by the compiler within the context of objc objects.  An obvious one  
would be that the attribute only applies to the class it was declared  
for and nothing else, even subclasses.




Obvious candidates are immutable objects 'length', 'count', etc,  
which would result in a pretty big win if these attributes were  
available.


If I write

- (void)doSomething:(NSArray *)array {
NSUInteger count1 = [array count];
NSUInteger count2 = [array count];
NSLog(@"%u", count1);
NSLog(@"%u", count2);
}

the compiler can't collapse those into a single invocation of - 
count.  After all, it could be passed a subclass of NSArray for whom  
-count has side-effects.  Think about a "thread-safe array" (as bad  
as the concept might be) for example.


Well, in the case of your example, you have a bug: You have statically  
typed the class to NSArray, not your subclass.  If one applies the  
'attribute only applies to the class it was specified for' rule:


By statically typing the class to NSArray, you have certified to the  
compiler that no other object t

Re: Garbage collector vs variable lifetime

2008-06-08 Thread Peter Duniho

Date: Mon, 9 Jun 2008 01:03:16 -0400
From: John Engelhart <[EMAIL PROTECTED]>

On Jun 7, 2008, at 10:10 PM, Michael Ash wrote:


If you don't like undefined behavior, then C-based languages are a
poor choice. If you don't like nondeterministic object lifetimes,  
then

garbage collection is a poor choice.


If your statement regarding nondeterministic object lifetimes is true,
and (as I think it has been shown) deterministic object lifetimes is
sometimes required for deterministic program behavior, does this not
imply that the current GC system is fundamentally flawed?


Not at all.  A GC system doesn't have non-deterministic object  
lifetimes.  It has non-deterministic object deaths.


The lifetime of an object under GC is well-defined, at least with  
respect to code correctness.  As long as code is actually using a GC- 
managed object, the lifetime of the object is assured.  It is only  
when the object becomes unreachable that its lifetime _may_ be ended,  
and the very moment that the object becomes unreachable, no code had  
better depend on that object staying alive.


The lifetime may be extended arbitrarily by the GC system, but this  
is immaterial to correct code.  And in fact, a non-GC system could do  
the same thing.


For example, imagine a non-GC memory manager that had a separate  
thread responsible for returning objects that have been freed/deleted  
to the free-list...that data would theoretically be usable until the  
thread gets around to putting it back in the free-list, and in fact  
probably even until the memory was then reallocated by something  
else.  But surely you would not consider code correct if it continued  
to reference and use memory that had been passed to free/delete.  Right?


In either case, once the code has discarded its last reference to the  
memory (either by the reference simply no longer existing, as in a GC  
system, or by calling a memory management function like free or  
delete, as in some other systems), the memory management system is  
free to deal with that block of memory as it likes.  Code that relies  
on the the data in memory sticking around even after it no longer is  
referencing the memory is what's flawed, not the memory manager.


The non-determinism that exists in a GC system (and this is not at  
all unique to Obj-C's system) is absolutely not "fundamentally  
flawed".  It won't affect correct code at all.


Pete
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread John Engelhart
er returned by UTF8String.  One can say with certainty that  
utf8StringCopy is valid under all uses, to any function, method, or C- 
only library function until the end of the enclosing block, regardless  
of the behavior of the GC collector.


Using the raw UTF8String pointer is far, far more convenient, and very  
likely to work 99.99% of the time without problems.


Convenience, however, rarely trumps correctness.



The compiler and garbage collector both do their jobs. They keep the
object around as long as it is referenced, after which it becomes a
candidate for collection. The trouble is just that where it stops
being referenced and where you think it should stop being referenced
are not the same place.


I think this argues for the case that __strong pointers should not  
necessarily be treated as equivalents to regular pointers.  As I  
previously suggested, appending the pointer rules such that 'A  
__strong pointer will remain visible to the GC system from the point  
in which it is defined until the end of its enclosing block.' would  
seem to better reflect peoples expected behavior, rather than actual  
behavior.


This really highlights the danger of bolting such features on to an  
existing compiler and language.  There are decades of extremely subtle  
implied invariants built in to the assumptions used to code the GCC  
compiler, especially when it comes to optimization transformations.   
Some of these are no longer true when it comes to __strong pointers,  
or they create undesirable, subtle side effects.



Now it's your turn -- where is the problem with the compiler marking
references you have *semantically* placed on the stack as strong,
whether or not they really end up on the stack after optimisation?


The problem is that this proposal doesn't make any sense given the
architecture of the Cocoa GC. The GC considers the stack plus
registers of each thread to be one big blob which it then scans for
anything that looks like a pointer. There's no way to mark anything as
being "strong", because the collector considers everything on the
stack to be strong. Even if this were to be resolved it still wouldn't
help because the problem isn't that the data pointer isn't strong, the
problem is that the data pointer *goes away*. No amount of annotation
will fix that; you have to change the compiler to keep object pointers
on the stack through the end of the current scope, and if you make
that change then the annotation is unnecessary anyway.


Actually, one has to tackle the issue of "places it on the stack" as  
well, since the language itself does not specify nor require the use  
of a stack.  One would really need a new storage class specifier, much  
like 'auto' and 'register', with the obvious candidate being 'stack'.   
As it stands, block local auto __strong pointers are implied to reside  
on the stack, not explicitly required to reside on the stack.   
Otherwise, one is stuck with a very subtle coupling of language  
specification to implementation requirement which I think should  
remain distinct.  In fact, it's a subtle coupling of language  
specification to the specific implementation details of Leopards GC  
system.


Granted, this is a pedantic point, but I think it's important to be  
explicit in such matters.  This whole thread has really shown that  
there is an uneven application of the 'rules' when it comes to GC.  It  
also highlights the fact that the current documentation regarding the  
GC system is woefully inadequate when it comes to resolving some of  
these finer, nuanced points.




I disagree. Since the programmer cannot possibly know the state of  
the

call stack in any other way than by knowing that the compiler must
keep references to objects right up to the point where those objects
are no longer used, he must not make any assumption as to the  
lifetime

of those objects beyond that point.


But who is to say the compiler won't make optimisations which alter
when the object is last referenced? (See my reply to Peter for a code
example.)


As Chris Hanson pointed out, the compiler cannot move function or
method calls without changing the underlying semantics of the code, so
you're guaranteed to be safe by doing a [data self] or equivalent at
the end of the loop. You can also, of course, use CFRetain/CFRelease
to more explicitly manage its lifetime.


As I pointed out, even this is not necessarily true.  The GCC  
__attributes(()) of 'const' and 'pure' can render this assumption  
invalid if they were to be extended to objc methods (and since I  
realized that I haven't actually tried it, just might be).


Also, a strict reading of the documentation for CFRetain and CFRelease  
give no indication of their behavior under GC.  In the absence of  
anything explicit, I would think that the standard 'toll-free  
brid

Re: Garbage collector vs variable lifetime

2008-06-08 Thread Chris Hanson

On Jun 8, 2008, at 5:39 PM, John Engelhart wrote:


On Jun 7, 2008, at 7:11 PM, Chris Hanson wrote:

This won't happen because each message expression -- just as with  
function-call expressions -- is a sequence point.  The compiler  
can't know what side-effects [data self] might have, so it can't re- 
order the invocation to elsewhere.


This is not necessarily true.  If the const and pure GCC  
__attribute(())s were extended to objc methods then the compiler  
would be free to perform common subexpression and loop invariant  
code movement optimizations.


They can't be, while preserving the existing semantics of the  
language.  In the existing semantics, a message send always results in  
a dynamic dispatch.


 The 'self' message would definitely fall under the domain of these  
attributes, thus the original argument is apropos.


For source compatibility, you almost certainly could *not* suddenly  
indicate that "[foo self]; [foo self];" results in only one invocation  
of -self by the compiler, at least for subclasses of NSObject or  
NSProxy.


After all, a subclass of NSObject may have overridden -self to do  
something else, and the compilation unit containing the above two  
invocations may have no idea what the class of "foo" is with which to  
make that judgment.


Obvious candidates are immutable objects 'length', 'count', etc,  
which would result in a pretty big win if these attributes were  
available.


If I write

  - (void)doSomething:(NSArray *)array {
  NSUInteger count1 = [array count];
  NSUInteger count2 = [array count];
  NSLog(@"%u", count1);
  NSLog(@"%u", count2);
  }

the compiler can't collapse those into a single invocation of -count.   
After all, it could be passed a subclass of NSArray for whom -count  
has side-effects.  Think about a "thread-safe array" (as bad as the  
concept might be) for example.


Adding additional attributes to make any new API contracts stricter is  
an interesting idea, but it's likely to result in breakage of existing  
code either at runtime or during compilation.


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread John Engelhart


On Jun 7, 2008, at 7:11 PM, Chris Hanson wrote:


On Jun 6, 2008, at 5:36 PM, Quincey Morris wrote:

A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


This won't happen because each message expression -- just as with  
function-call expressions -- is a sequence point.  The compiler  
can't know what side-effects [data self] might have, so it can't re- 
order the invocation to elsewhere.


 -- Chris


This is not necessarily true.  If the const and pure GCC  
__attribute(())s were extended to objc methods then the compiler would  
be free to perform common subexpression and loop invariant code  
movement optimizations.  The 'self' message would definitely fall  
under the domain of these attributes, thus the original argument is  
apropos.  Considering the relative ease of extending this to objc  
methods and the possible performance gains, it's probably a given that  
this will happen eventually.  Obvious candidates are immutable objects  
'length', 'count', etc, which would result in a pretty big win if  
these attributes were available.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread Chris Kane

On Jun 7, 2008, at 6:59, Ricky Sharp wrote:
I will hope though that within the context of say memcpy, that the  
GC thread could not collect data.  For example, the following  
should be safe:


memcpy(myLocalGCAwareBuffer, [data bytes], numberOfBytes);


No.  This is equivalent to:

void *tmp073495 = [data bytes];	// <<< last use of 'data', as  
previously discussed

... other "harmless" stuff could be put here by the compiler ...
// <  GC could run here, or not; mystery crash 0.7% of the time
memcpy(myLocalGCAwareBuffer, tmp073495, numberOfBytes);

to the compiler.  There is a sequence point between the evaluation of  
all the function call arguments and the call to the function, but it  
doesn't follow that the two things are right next to each other.   
Depends on what else is going on in the surrounding code.  The  
sequence point just ensures that all side effects from the argument  
evaluation are complete before the function begins.



On 7 Jun 2008, at 09:07, Antonio Nunes wrote:

On 7 Jun 2008, at 06:16, Ken Thomases wrote:

The issue is, how can one know when this technique is necessary?



By proper documentation. As Bill mentioned earlier, the  
documentation needs to mention this behaviour. Just as retain/ 
release, GC has its own caveats, it's own moments where one has to  
take special care. This appears to be one of them. If I read Bill's  
explanation correctly then once the documentation gets updated and  
distributed anyone can know when this technique is necessary (as  
long as they know what they're doing, which goes for anything in  
programming).




Oh, yes, it's just that simple.  Even  
understanding the potential does not necessarily lead to recognizing  
when special action needs to be taken.  In amongst the hundred other  
things you have to keep in mind as you write a method, there will  
also be, "let's see, is this the last use of this object in this 100- 
line method? Hmm, yes, it appears so.  Let's see,  
do I need to take any special actions ...? OK, now what about this  
next object ...?" etc.  And what about code which already exists,  
such as "millions" of lines of Cocoa/ObjC code in the OS frameworks?   
Somebody has gone over years of accummulated "optimized" code with a  
fine-tooth comb to find such things?  I'll say no more; these are  
just hypothetical statements pointing out the shallowness of a  
"documentation bandaid" approach.


It'd be much better if the tools could warn you about such things in  
the source code.  Or something.



I think Bill summarized this whole discussion, and 90% of other  
garbage collection discussions, brilliantly in these 8 words:


On 6 Jun 2008, at 16:42, Bill Bumgarner wrote:

Under GC, the situation isn't quite so clear.



Once upon a time, for this kind of thing, people would say things  
like "That's going in my quotes file!", ... back when people kept  
quotes files



On Jun 6, 2008, at 9:16 PM, Ken Thomases wrote:
Quoting the Garbage Collection Programming Guide: "The initial root  
set of objects is comprised of global variables, stack variables,  
and objects with external references. These objects are never  
considered as garbage"

For some values of "never".


This, and the so-called "C code" using the bytes pointer from a data,  
reminded me of some lines from a Gilbert and Sullivan opera ...


GC: [...]
I am never known to quail
At the fury of a gale,
And I'm never, never sick at C!
Chorus:
What, never?
GC:
No, never!
Chorus:
What, never?
GC:
Hardly ever!
Chorus:
He's hardly ever sick at C!
[...]


Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread Paul Sargent


On 8 Jun 2008, at 01:23, Bill Bumgarner wrote:

One of the tenets of GCC is that *it controls the layout of the  
stack always* and this is done quite explicitly because of  
performance.


I think this is the crucial point when considering how any GC will  
work with gcc.


If gcc controls the stack, it's impossible for the programmer to  
dictate what is in the root set. They can make some suggestions, and  
possibly influence it with hacks (such as [data self]), but absolute  
control is ceded to the compiler.


It's a fundamental truth for any GC on top of gcc, and one that makes  
the job of writing the GC one I wouldn't ever want. I don't think it's  
possible to make a 100% fool proof GC without more compiler support,  
or internal pointer support (which is non-trivial).



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread Hamish Allan
On Sun, Jun 8, 2008 at 3:10 AM, Michael Ash <[EMAIL PROTECTED]> wrote:

> In many cases, including this one, the release build is actually
> exposing faulty code, whereas the debug build is hiding it by working
> as the programmer wants it to despite the code not actually being
> correct.

My thanks to you and everyone else in this thread who helped me to
realise the gap between my understanding of "putting a variable on the
stack" and the realities of how the Obj-C 2.0 GC works.

I shall learn to stop worrying and love the bomb :)

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread Hamish Allan
On Sun, Jun 8, 2008 at 1:23 AM, Bill Bumgarner <[EMAIL PROTECTED]> wrote:

> Consider:
>
> {
>int foo;
>
>... calculate on foo ...
>
>int bar = getirdone(foo);
>
>while(1) {
>func(bar);
>func2(bar);
>... etc ...
>}
> }
>
> Without being able to recycle the space used by foo and bar, the compiler
> will generate code the pays the price of that space being consumed for all
> of the while loop, which could be the vast majority of the run time of the
> application.
>
> As well, if foo / bar fall in a register, then those registers would have to
> be preserved for all of the while loop, too, either by not being available
> to the bulk of the program (which raises some serious codegen issues) or
> being moved out/in the registers every time one of the funcs in the while
> loop is called or returns.

I was thinking that after the call to getirdone(foo), instead of
simply overwriting the value of foo in the register, the compiler
could move it to a space on the stack it had previously reserved for
that purpose.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-08 Thread Hamish Allan
Hi Peter,

On Sun, Jun 8, 2008 at 1:15 AM, Peter Duniho <[EMAIL PROTECTED]> wrote:

> Maybe it's just because I've been using GC systems more than you have, and
> so I've gotten used to thinking about memory allocations in the paradigm
> that GC systems impose.

I'm starting to realise that this is my barrier. I'm just an
Obj-C/Cocoa programmer who never had any objection to version 1 memory
management and is a bit alarmed to discover that I can't control the
scope of my objects' lifetimes as easily as I could with an
autorelease pool.

> That's because the root of this problem isn't the
> optimizing compiler.  It's the fact that garbage collection is being used
> alongside other forms of memory management.  It's only because there are
> things that are allocated outside of the garbage collection system that this
> even comes up.

Indeed, although I've used several other GC languages before, I've
never tried to mix GC with non-GC before.

>> The compiler is already in that business -- hence the modifiers
>> __strong and __weak.
>
> Not really.  In fact, if anything those are proof that the compiler is _not_
> in the business of memory management.  Instead, it provides a way for YOU to
> give it information that is used to control memory management.  If the
> compiler were in the business of memory management, it would infer those
> properties itself.

I guess what I meant is: the compiler is in the business of telling
the GC what it can and cannot collect.

>>> and b) there will still be lots of other scenarios that
>>> are similar, but not solvable by the compiler.
>>
>> Could you please elaborate on this?
>
> I'm surprised I need to.
>
> But, consider the NSData example we've been using.  Suppose that the byte*
> in question weren't just used locally, but rather passed to some other data
> structure.  Even if we "fixed" the compiler so that it didn't optimize away
> the variable referencing the "data" object, when that variable goes out of
> scope as the method returns, the byte* still would potentially be released,
> as the "data" object is.

Yes, but this is nothing to do with the discussion at hand. We are
talking about the lifetime of the NSData object. This "inner pointer"
class of problems existed with autorelease, too, but because the
lifetime of autoreleased objects was deterministic, it was easier to
handle.

> No one said anything about _referencing_ "data".  You have to _use_ it in a
> way that the compiler _can't_ rearrange.

Okay, I think I understand these usages now.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Quincey Morris


On Jun 7, 2008, at 17:23, Bill Bumgarner wrote:

As well, if foo / bar fall in a register, then those registers would  
have to be preserved for all of the while loop, too, either by not  
being available to the bulk of the program (which raises some  
serious codegen issues) or being moved out/in the registers every  
time one of the funcs in the while loop is called or returns.


The realities of register allocation are a strong enough reason to let  
the compiler go on optimizing variable lifetimes the way it does now.  
Fine. Moving on from there, the consequence is that -[NSData bytes]  
and -[NSMutableData mutableBytes] start looking very dangerous, and at  
the same time high profile from a coding point of view.


As Michael Ash has also been suggesting, the danger would be  
eliminated if the pointers returned by bytes/mutableBytes were also GC- 
references -- meaning that they were recognized by the GC as keeping  
something or other alive so that their pointer values remain valid.  
This might be done by having them point to collectable blocks, or by  
enhancing the GC to recognize them in some other way, the exact  
methodology being an implementation detail.


I know you are reluctant to engage in useless speculation, but I  
wonder if you know a reason why bytes/mutableBytes pointers should not  
or could not be GC-references in this possibly expanded sense. Such a  
change would simply solve the entire problem out of hand.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 6:37 PM, Hamish Allan <[EMAIL PROTECTED]> wrote:
> On Sat, Jun 7, 2008 at 7:35 PM, Michael Ash <[EMAIL PROTECTED]> wrote:
>
>> This is pretty nitpicky. If it's in scope but you don't use it, then
>> it doesn't matter. Kind of like a Zen koan: if an object is collected
>> in the forest but nobody is pointing to it anymore, does it make a
>> sound?
>
> :)
>
> I'm just arguing that it makes it more straightforward if the GC
> behaves deterministically according to the code you wrote, rather than
> what the optimising compiler re-wrote for you.

If you don't like undefined behavior, then C-based languages are a
poor choice. If you don't like nondeterministic object lifetimes, then
garbage collection is a poor choice.

The compiler and garbage collector both do their jobs. They keep the
object around as long as it is referenced, after which it becomes a
candidate for collection. The trouble is just that where it stops
being referenced and where you think it should stop being referenced
are not the same place.

>>>> How would it be less straightforward? If it returned collected memory
>>>> then everything will Just Work for the common case of using the
>>>> pointer on the stack. You would also have the additional convenience
>>>> of being able to safely store the returned pointer in a __strong heap
>>>> variable, something which you simply cannot do under non-GC rules at
>>>> all. Looks like there are only improvements to me, where is the
>>>> problem?
>>>
>>> I agree with you that if it returned collected memory, it would be
>>> more powerful than under retain/release/autorelease. But power and
>>> straightforwardness do not always go hand in hand ;)
>>
>> Hmm, you didn't answer my question though. Where exactly is the
>> problem? For the case where the old-style rules also work, it would be
>> precisely as straightforward. (In case your objection is with the
>> __strong qualifier, note that you would not need that for a local
>> variable, only for instance variables.)
>
> Where is the problem with having NSData return collected memory? I
> have no problem with that, I just don't think it solves the whole
> problem.

The problem is that NSData sometimes wraps memory which is abnormal.
For example, +[NSData dataWithContentsOfMappedFile:] most likely uses
mmap (or the mach equivalent) under the hood. This then requires the
use of munmap (or the mach equivalent) to free that memory. The Cocoa
GC currently doesn't support such custom allocation and deallocation
schemes, so NSData can't use collected memory in the general case. It
could use it for *most* cases, but that would just make this problem
occur even more inconsistently.

> Now it's your turn -- where is the problem with the compiler marking
> references you have *semantically* placed on the stack as strong,
> whether or not they really end up on the stack after optimisation?

The problem is that this proposal doesn't make any sense given the
architecture of the Cocoa GC. The GC considers the stack plus
registers of each thread to be one big blob which it then scans for
anything that looks like a pointer. There's no way to mark anything as
being "strong", because the collector considers everything on the
stack to be strong. Even if this were to be resolved it still wouldn't
help because the problem isn't that the data pointer isn't strong, the
problem is that the data pointer *goes away*. No amount of annotation
will fix that; you have to change the compiler to keep object pointers
on the stack through the end of the current scope, and if you make
that change then the annotation is unnecessary anyway.

>> I disagree. Since the programmer cannot possibly know the state of the
>> call stack in any other way than by knowing that the compiler must
>> keep references to objects right up to the point where those objects
>> are no longer used, he must not make any assumption as to the lifetime
>> of those objects beyond that point.
>
> But who is to say the compiler won't make optimisations which alter
> when the object is last referenced? (See my reply to Peter for a code
> example.)

As Chris Hanson pointed out, the compiler cannot move function or
method calls without changing the underlying semantics of the code, so
you're guaranteed to be safe by doing a [data self] or equivalent at
the end of the loop. You can also, of course, use CFRetain/CFRelease
to more explicitly manage its lifetime.

If you're doubtful about this, consider what would happen in a boring
non-collected environment if the compiler were allowed to move this
stuff around. A [obj rele

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Chris Hanson

On Jun 6, 2008, at 5:36 PM, Quincey Morris wrote:

A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


This won't happen because each message expression -- just as with  
function-call expressions -- is a sequence point.  The compiler can't  
know what side-effects [data self] might have, so it can't re-order  
the invocation to elsewhere.


  -- Chris

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Bill Bumgarner

On Jun 7, 2008, at 3:51 PM, Hamish Allan wrote:

Sorry to reply to myself, but I just remembered that pointers in
registers are also in the root set! That said, I don't think it
changes the substance of my proposal: that stack variables (i.e.
variables semantically placed on the stack by the programmer) should
remain in the root set until they are out of scope (i.e. semantically
no longer in the current stack frame).


That leads to significantly slower code.   If you have some C based  
performance test suite available, compile it at the different  
optimization levels and see how the numbers change.  You can even turn  
on/off specific optimizations and see the impact.


In particular, a common optimization is to use registers to store  
local variables and/or arguments.  This would no longer be viable if  
the compiler couldn't recycle locals when they fall out of scope.   Or  
it would be exceedingly expensive as the compiler would have to  
generate code to save and restore registers across call sites.


Consider:

{
int foo;

... calculate on foo ...

int bar = getirdone(foo);

while(1) {
func(bar);
func2(bar);
... etc ...
}
}

Without being able to recycle the space used by foo and bar, the  
compiler will generate code the pays the price of that space being  
consumed for all of the while loop, which could be the vast majority  
of the run time of the application.


As well, if foo / bar fall in a register, then those registers would  
have to be preserved for all of the while loop, too, either by not  
being available to the bulk of the program (which raises some serious  
codegen issues) or being moved out/in the registers every time one of  
the funcs in the while loop is called or returns.


One of the tenets of GCC is that *it controls the layout of the stack  
always* and this is done quite explicitly because of performance.


b.bum

smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Peter Duniho

Date: Sat, 7 Jun 2008 23:24:22 +0100
From: "Hamish Allan" <[EMAIL PROTECTED]>

Whenever you write documentation in a natural language, there is scope
for ambiguity. This particular technical specification is only
mentioned in a single sentence:

"The root set is comprised of all objects reachable from root objects
and all possible references found by examining the call stacks of
every Cocoa thread."


Is that the actual specification for the garbage collector?  Or just  
some documentation provided by Apple?


In any case...


Are you seriously telling me that "all *possible* references found by
examining the calls stacks" unambiguously means "all *actual*
references found by examining the rest of the code in the block"?


I'm not telling you that at all.  I don't actually know how the Obj-C  
GC works, but from what's been written here, it appears to me that  
it's not looking at code, but rather it's looking at data.


It doesn't need to examine the code to know whether there's a value  
in the stack that refers to the object.  If it walks all the stack  
frames and doesn't find a reference to the object, then no code can  
possibly be referencing the object via a local variable.


It is available for my use until the end of that scope. The fact  
that

I don't actually make use of it, and the optimising compiler thinks
I'm done with it: *that*'s an implementation detail.


No, it's not.  It's a _semantic_ detail.  If you do in fact not  
use the
reference, then it is in fact _unused_.  Garbage collection is all  
about

what's being used or not.


You'll notice that I was replying to a specific point Michael made:
"the promise that is being made is that objects which you're still
pointing to won't go away".


He can speak for himself, but I believe that statement was made in  
context of the run-time status.  And if the compiler optimizes out a  
variable, indeed it may be that you're not still "pointing to" that  
particular object.



I don't disagree that "have a pointer"
means something different to "use a pointer".


I don't think it's necessary to consider those to have different  
meanings for the behavior of the compiler to make sense, even in the  
context of garbage collection.  If you have no code that "uses the  
pointer", then the compiler is free to use that memory location for  
something else, at which point you no longer "have a pointer".  The  
two are very much related.



Which part of the
documentation unambiguously specifies that "Garbage collection is all
about what's being used or not"?


Ahhh...please, I'm not trying to defend the documentation.  If you  
find something in the documentation that is misleading or incomplete,  
that's no surprise to me.  That happens in documentation (and not  
just Apple's) all the time.  Especially for relatively new features.


As far as I'm concerned, the only question is whether the behavior of  
the compiler and its effect on the GC makes sense.  And it's my  
opinion that it does.



Even if the compiler did not optimize away the
use of the variable past that point in the code, if the GC system  
could
otherwise determine you weren't ever going to use it again, it  
would _still_

be valid for the GC system to collect the object.


If you could write a garbage collector that could reliably detect what
was being used, you'd have no need to specify __strong or __weak any
more, and you'd have solved the halting problem to boot. We're not
quite at that stage yet :)


So?  My point is that whatever the theoretical capabilities of the  
GC, as long as you haven't written code that will actually use a  
reference to an object, the GC should be allowed to collect the  
object.  The fact that writing such an advanced GC is theoretically  
impossible is immaterial.


That's why we call these "hypothetical" examples.  :)


I agree with you that if it returned collected memory, it would be
more powerful than under retain/release/autorelease. But power and
straightforwardness do not always go hand in hand ;)


Well, in this case I believe they do.  The real issue here is that  
a garbage
collection system is trying to co-exist peacefully with a non-GC  
system.


I disagree. The real issue here is that code optimisations cause
different behaviour in the GC,


Define "different".  In every GC system I've ever used, there are  
never any guarantees about when an object may be collected, except  
that it won't be collected until it's no longer in use.  The fact  
that in the debug build, an object is collected _later_ than would  
theoretically be possible in an optimized build doesn't mean that the  
GC system is broken.  It just means

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 11:24 PM, Hamish Allan <[EMAIL PROTECTED]> wrote:

> Sure, you could design NSData differently to mask a design problem in
> GC. But GC won't be easier to use than retain/release/autorelease
> without simple rules like "if you declare it on the stack, it's in the
> root set, regardless of whether the compiler optimises it into a
> register".

Sorry to reply to myself, but I just remembered that pointers in
registers are also in the root set! That said, I don't think it
changes the substance of my proposal: that stack variables (i.e.
variables semantically placed on the stack by the programmer) should
remain in the root set until they are out of scope (i.e. semantically
no longer in the current stack frame).

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 7:35 PM, Michael Ash <[EMAIL PROTECTED]> wrote:

> This is pretty nitpicky. If it's in scope but you don't use it, then
> it doesn't matter. Kind of like a Zen koan: if an object is collected
> in the forest but nobody is pointing to it anymore, does it make a
> sound?

:)

I'm just arguing that it makes it more straightforward if the GC
behaves deterministically according to the code you wrote, rather than
what the optimising compiler re-wrote for you.

> Objects stay live for as long as you reference them, period. This is
> what the collector guarantees and this is what the real-world behavior
> is. The problem occurs when you try to reference their contents after
> you stop referencing the objects themselves. The documentation says
> nothing about scope, it talks about the stack. The stack is already an
> implementation detail, so if you're going to examine that promise then
> you absolutely need to examine those implementation details.

I guess so! But it means that that promise is worth about as much as
an inner pointer ;)

>>> How would it be less straightforward? If it returned collected memory
>>> then everything will Just Work for the common case of using the
>>> pointer on the stack. You would also have the additional convenience
>>> of being able to safely store the returned pointer in a __strong heap
>>> variable, something which you simply cannot do under non-GC rules at
>>> all. Looks like there are only improvements to me, where is the
>>> problem?
>>
>> I agree with you that if it returned collected memory, it would be
>> more powerful than under retain/release/autorelease. But power and
>> straightforwardness do not always go hand in hand ;)
>
> Hmm, you didn't answer my question though. Where exactly is the
> problem? For the case where the old-style rules also work, it would be
> precisely as straightforward. (In case your objection is with the
> __strong qualifier, note that you would not need that for a local
> variable, only for instance variables.)

Where is the problem with having NSData return collected memory? I
have no problem with that, I just don't think it solves the whole
problem.

Now it's your turn -- where is the problem with the compiler marking
references you have *semantically* placed on the stack as strong,
whether or not they really end up on the stack after optimisation?

> I disagree. Since the programmer cannot possibly know the state of the
> call stack in any other way than by knowing that the compiler must
> keep references to objects right up to the point where those objects
> are no longer used, he must not make any assumption as to the lifetime
> of those objects beyond that point.

But who is to say the compiler won't make optimisations which alter
when the object is last referenced? (See my reply to Peter for a code
example.)

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 7:34 PM, Peter Duniho <[EMAIL PROTECTED]> wrote:

>> Date: Sat, 7 Jun 2008 15:31:43 +0100
>> From: "Hamish Allan" <[EMAIL PROTECTED]>
>>
>> We're just interpreting this promise differently. To my mind, while
>> the variable is still in scope, I *do* have a pointer to the object.
>
> All due respect, "to my mind" isn't a valid technical specification.

Whenever you write documentation in a natural language, there is scope
for ambiguity. This particular technical specification is only
mentioned in a single sentence:

"The root set is comprised of all objects reachable from root objects
and all possible references found by examining the call stacks of
every Cocoa thread."

Are you seriously telling me that "all *possible* references found by
examining the calls stacks" unambiguously means "all *actual*
references found by examining the rest of the code in the block"?

>> It is available for my use until the end of that scope. The fact that
>> I don't actually make use of it, and the optimising compiler thinks
>> I'm done with it: *that*'s an implementation detail.
>
> No, it's not.  It's a _semantic_ detail.  If you do in fact not use the
> reference, then it is in fact _unused_.  Garbage collection is all about
> what's being used or not.

You'll notice that I was replying to a specific point Michael made:
"the promise that is being made is that objects which you're still
pointing to won't go away". I don't disagree that "have a pointer"
means something different to "use a pointer". Which part of the
documentation unambiguously specifies that "Garbage collection is all
about what's being used or not"?

> Even if the compiler did not optimize away the
> use of the variable past that point in the code, if the GC system could
> otherwise determine you weren't ever going to use it again, it would _still_
> be valid for the GC system to collect the object.

If you could write a garbage collector that could reliably detect what
was being used, you'd have no need to specify __strong or __weak any
more, and you'd have solved the halting problem to boot. We're not
quite at that stage yet :)

>> I agree with you that if it returned collected memory, it would be
>> more powerful than under retain/release/autorelease. But power and
>> straightforwardness do not always go hand in hand ;)
>
> Well, in this case I believe they do.  The real issue here is that a garbage
> collection system is trying to co-exist peacefully with a non-GC system.

I disagree. The real issue here is that code optimisations cause
different behaviour in the GC, whereas if the GC behaved according to
rules based on the *semantics* of what the programmer writes (i.e.
what would happen if that variable were really on the stack, rather
than optimised away into a register), there wouldn't be a problem (the
optimisation could still happen, of course, but the compiler would
flag that reference as strong).

> GC
> systems have been around for a long time, but in many of the examples, the
> entire environment is garbage-collected and this sort of thing just doesn't
> come up in normal code.

Sure. I'm not trying to say I could have designed a perfect GC system
for Objective-C, I'm just trying to point out how I would change this
one for the better.

> That said, even in .NET (for example), the GC system has a "GC.KeepAlive()"
> method for this very purpose.  It doesn't actually do anything, but it
> interrupts optimizations the compiler might make that would otherwise allow
> an object to be collected (it would be used exactly as the proposed "[data
> self]" call would be).  This is to allow for situations where the only
> reference to the object is in "unmanaged" code -- that is, it's been passed
> across the interface from .NET to the older non-GC'ed Windows API.

Again, I think that signalling to the GC that you don't want the
object collected by creating a stack variable reference to it --
whether or not that variable ever actually ends up on the stack due to
optimisations -- is quite enough. No need for GC.KeepAlive(), [data
self], CFRetain(), disableCollectionForPointer, or any other hack.

> [snip]
>
> Not only is it not a bug for the compiler to not concern itself with the
> issue, the fact is that the extant example here is just the tip of the
> iceberg.  While you might argue that the compiler _could_ prevent this
> particular problem, a) it requires the compiler to get into the business of
> memory management

The compiler is already in that business -- hence the modifiers
__strong and __weak.

> and b) the

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Ricky Sharp


On Jun 7, 2008, at 2:07 PM, Jean-Daniel Dupas wrote:



Le 7 juin 08 à 20:30, Michael Ash a écrit :


On Sat, Jun 7, 2008 at 9:59 AM, Ricky Sharp <[EMAIL PROTECTED]> wrote:
I will hope though that within the context of say memcpy, that the  
GC thread

could not collect data.  For example, the following should be safe:

memcpy(myLocalGCAwareBuffer, [data bytes], numberOfBytes);


Not at all. The semantics of this is identical to the semantics of
just writing your own loop. Nothing guarantees that the data pointer
stays on the stack during the memcpy. If nothing else references the
data then you *must* either ensure that a reference stays on the  
stack

(by, for example, messaging it afterwards) or you must disable
collection for it until you're done with its contents.



This is not a problem, just replace thoses two calls by a single  
method invocation:  -[NSData getBytes:buffer length:length];



That would definitely work quite nicely.
___
Ricky A. Sharp mailto:[EMAIL PROTECTED]
Instant Interactive(tm)   http://www.instantinteractive.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Ricky Sharp


On Jun 7, 2008, at 1:30 PM, Michael Ash wrote:


On Sat, Jun 7, 2008 at 9:59 AM, Ricky Sharp <[EMAIL PROTECTED]> wrote:
Finally, I think that usages of NSMutableData may also be a bit  
tricky.  In
my case I'll probably just obtain a copy of its bytes, manipulate  
them and

then copy the result back in. Sort of ironic though in that the inner
pointer would have been valid anyhow in such blocks of code (the
NSMutableData instance would be around between the get and  
subsequent set of

its bytes):

NSMutableData* data = [...];
const unsigned char* bytes = [data bytes];
operate on copy of bytes in GC-aware buffer
[data replaceBytesInRange:...];


This is unnecessary, since data is guaranteed to stay live throughout
your operation because you use it at the end. You only need to take
measures when your last reference to the NSData object comes before
your last reference to its bytes pointer.



That's why I called it 'ironic' in my description.  The block above  
messages data at the end, so yes, no need to do the copies.  But, code  
that typically just works on the mutableBytes would be:


NSMutableData* data = [...];
unsigned char* bytes = [data mutableBytes];
operate on bytes

Here, we have the same issue.
___
Ricky A. Sharp mailto:[EMAIL PROTECTED]
Instant Interactive(tm)   http://www.instantinteractive.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Jean-Daniel Dupas


Le 7 juin 08 à 20:30, Michael Ash a écrit :


On Sat, Jun 7, 2008 at 9:59 AM, Ricky Sharp <[EMAIL PROTECTED]> wrote:
I will hope though that within the context of say memcpy, that the  
GC thread

could not collect data.  For example, the following should be safe:

memcpy(myLocalGCAwareBuffer, [data bytes], numberOfBytes);


Not at all. The semantics of this is identical to the semantics of
just writing your own loop. Nothing guarantees that the data pointer
stays on the stack during the memcpy. If nothing else references the
data then you *must* either ensure that a reference stays on the stack
(by, for example, messaging it afterwards) or you must disable
collection for it until you're done with its contents.



This is not a problem, just replace thoses two calls by a single  
method invocation:  -[NSData getBytes:buffer length:length];





smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 2:19 PM, Quincey Morris
<[EMAIL PROTECTED]> wrote:
> The consequence of this should be either:
>
> (a) [data bytes] must promise to return a collectable object (so that the
> 'bytes' reference keeps it alive), or
>
> (b) [data bytes] must lock (pseudo-retain) something internally (possibly
> just 'data' itself) and be matched with an unlock (pseudo-release) method.
>
> (Maybe there's a 3rd option, but I can't think of it. Your custom allocator
> suggestion is more or less equivalent to (b), I think.)

The custom allocator idea would actually be a way of implementing
option (a). I assume the reason (a) isn't used now, aside from simple
legacy or not having thought about it, is because sometimes NSData
wraps pointers which *can't* be collected, because they need to be
"freed" using calls such as munmap and the current collector only
works with pointers that it allocates itself. Adding support for
custom allocators to the collector would allow such special cases to
work.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 10:31 AM, Hamish Allan <[EMAIL PROTECTED]> wrote:
> On Sat, Jun 7, 2008 at 2:18 PM, Michael Ash <[EMAIL PROTECTED]> wrote:
>
>> The business about scanning the stack is essentially an
>> implementation detail; the promise that is being made is that objects
>> which you're still pointing to won't go away.
>
> We're just interpreting this promise differently. To my mind, while
> the variable is still in scope, I *do* have a pointer to the object.
> It is available for my use until the end of that scope. The fact that
> I don't actually make use of it, and the optimising compiler thinks
> I'm done with it: *that*'s an implementation detail.

This is pretty nitpicky. If it's in scope but you don't use it, then
it doesn't matter. Kind of like a Zen koan: if an object is collected
in the forest but nobody is pointing to it anymore, does it make a
sound?

Objects stay live for as long as you reference them, period. This is
what the collector guarantees and this is what the real-world behavior
is. The problem occurs when you try to reference their contents after
you stop referencing the objects themselves. The documentation says
nothing about scope, it talks about the stack. The stack is already an
implementation detail, so if you're going to examine that promise then
you absolutely need to examine those implementation details.

>> How would it be less straightforward? If it returned collected memory
>> then everything will Just Work for the common case of using the
>> pointer on the stack. You would also have the additional convenience
>> of being able to safely store the returned pointer in a __strong heap
>> variable, something which you simply cannot do under non-GC rules at
>> all. Looks like there are only improvements to me, where is the
>> problem?
>
> I agree with you that if it returned collected memory, it would be
> more powerful than under retain/release/autorelease. But power and
> straightforwardness do not always go hand in hand ;)

Hmm, you didn't answer my question though. Where exactly is the
problem? For the case where the old-style rules also work, it would be
precisely as straightforward. (In case your objection is with the
__strong qualifier, note that you would not need that for a local
variable, only for instance variables.)

>> It *does* do this. The error is not in the GC, but rather in the
>> assumption that "declared in the current scope" is equivalent to "is
>> on the stack frame"
>
> Again, I see that as an implementation detail. From the documentation:
>
> "The root set is comprised of all objects reachable from root objects
> and all possible references found by examining the call stacks of
> every Cocoa thread."
>
> Given that the programmer cannot possibly know the state of the call
> stack any other way than by considering normal variable scoping rules,
> either it's meaningless to consider any variable on the stack as a
> root object, or the compiler needs to guarantee equivalence between
> them.

I disagree. Since the programmer cannot possibly know the state of the
call stack in any other way than by knowing that the compiler must
keep references to objects right up to the point where those objects
are no longer used, he must not make any assumption as to the lifetime
of those objects beyond that point.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Peter Duniho

Date: Sat, 7 Jun 2008 15:31:43 +0100
From: "Hamish Allan" <[EMAIL PROTECTED]>

On Sat, Jun 7, 2008 at 2:18 PM, Michael Ash <[EMAIL PROTECTED]>  
wrote:



The business about scanning the stack is essentially an
implementation detail; the promise that is being made is that objects
which you're still pointing to won't go away.


We're just interpreting this promise differently. To my mind, while
the variable is still in scope, I *do* have a pointer to the object.


All due respect, "to my mind" isn't a valid technical specification.


It is available for my use until the end of that scope. The fact that
I don't actually make use of it, and the optimising compiler thinks
I'm done with it: *that*'s an implementation detail.


No, it's not.  It's a _semantic_ detail.  If you do in fact not use  
the reference, then it is in fact _unused_.  Garbage collection is  
all about what's being used or not.  Even if the compiler did not  
optimize away the use of the variable past that point in the code, if  
the GC system could otherwise determine you weren't ever going to use  
it again, it would _still_ be valid for the GC system to collect the  
object.



How would it be less straightforward? If it returned collected memory
then everything will Just Work for the common case of using the
pointer on the stack. [...]


I agree with you that if it returned collected memory, it would be
more powerful than under retain/release/autorelease. But power and
straightforwardness do not always go hand in hand ;)


Well, in this case I believe they do.  The real issue here is that a  
garbage collection system is trying to co-exist peacefully with a non- 
GC system.  GC systems have been around for a long time, but in many  
of the examples, the entire environment is garbage-collected and this  
sort of thing just doesn't come up in normal code.


That said, even in .NET (for example), the GC system has a  
"GC.KeepAlive()" method for this very purpose.  It doesn't actually  
do anything, but it interrupts optimizations the compiler might make  
that would otherwise allow an object to be collected (it would be  
used exactly as the proposed "[data self]" call would be).  This is  
to allow for situations where the only reference to the object is in  
"unmanaged" code -- that is, it's been passed across the interface  
from .NET to the older non-GC'ed Windows API.


In .NET, a situation more like the one we're talking about here is  
less common -- unmanaged objects are (almost?) never passed to  
managed code without also passing responsibility for maintenance of  
that unmanaged object to the recipient -- but inasmuch as they might  
come up as well, using GC.KeepAlive() would also be required.  (Every  
single place I've come into contact with where an unmanaged object is  
passed back to managed code from a managed object, the recipient is  
required to free the object when they are done with it.  I suppose  
there might be an exception to that rule, but if there is, it's a  
very rare case).


I'm less familiar with how Java's memory management works, but given  
that it also has interfaces between the Java run-time and the host  
environment, I suspect it also has the same sort of potential issue.   
This is going to come up any time GC and non-GC are mixed; either a  
GC object will be held outside of the visibility of the GC system, or  
some non-GC object will be dependent on a GC object.  In either case,  
the programmer will have to be aware of this possibility and deal  
with it.


Not only is it not a bug for the compiler to not concern itself with  
the issue, the fact is that the extant example here is just the tip  
of the iceberg.  While you might argue that the compiler _could_  
prevent this particular problem, a) it requires the compiler to get  
into the business of memory management, and b) there will still be  
lots of other scenarios that are similar, but not solvable by the  
compiler.



It *does* do this. The error is not in the GC, but rather in the
assumption that "declared in the current scope" is equivalent to "is
on the stack frame"


Again, I see that as an implementation detail. From the documentation:

"The root set is comprised of all objects reachable from root objects
and all possible references found by examining the call stacks of
every Cocoa thread."

Given that the programmer cannot possibly know the state of the call
stack any other way than by considering normal variable scoping rules,
either it's meaningless to consider any variable on the stack as a
root object, or the compiler needs to guarantee equivalence between
them.


No.  As Mike points out, this is only a problem because the object is  
returning a pointer that the object itself can make invalid due to  
garbage collection, even while that pointer isn't itself subject to  
the GC rules.  This is a design problem, not a compiler error.


There are a variety of solutions, none of them spectacular.  It would  
be much better for

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 9:59 AM, Ricky Sharp <[EMAIL PROTECTED]> wrote:
> I will hope though that within the context of say memcpy, that the GC thread
> could not collect data.  For example, the following should be safe:
>
> memcpy(myLocalGCAwareBuffer, [data bytes], numberOfBytes);

Not at all. The semantics of this is identical to the semantics of
just writing your own loop. Nothing guarantees that the data pointer
stays on the stack during the memcpy. If nothing else references the
data then you *must* either ensure that a reference stays on the stack
(by, for example, messaging it afterwards) or you must disable
collection for it until you're done with its contents.

> Finally, I think that usages of NSMutableData may also be a bit tricky.  In
> my case I'll probably just obtain a copy of its bytes, manipulate them and
> then copy the result back in. Sort of ironic though in that the inner
> pointer would have been valid anyhow in such blocks of code (the
> NSMutableData instance would be around between the get and subsequent set of
> its bytes):
>
> NSMutableData* data = [...];
> const unsigned char* bytes = [data bytes];
> operate on copy of bytes in GC-aware buffer
> [data replaceBytesInRange:...];

This is unnecessary, since data is guaranteed to stay live throughout
your operation because you use it at the end. You only need to take
measures when your last reference to the NSData object comes before
your last reference to its bytes pointer.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Quincey Morris


On Jun 7, 2008, at 04:34, Michael Ash wrote:


Actually I think that it is about the char * pointer, and this bug
should be considered an NSData bug rather than a compiler bug or a GC
bug. The fact that it's really a design bug in NSData rather than
something that can be easily fixed definitely makes it worse, but
doesn't really change the location of the fault.


After obsessing about this some more, I think I might have come to  
much the same conclusion. The issue of whether the lifetime of a  
variable *should* be identical to the scope of the variable seems  
irresolvable, since there's no specification in control of the  
compiler's behavior AFAIK.


Going back to:

NSData*data = ...
const unsigned char* bytes = [data bytes];
for (...) {
... = bytes [i];
}

Since 'data' is not referenced in or beyond the loop, we don't care  
whether the NSData object gets garbage collected away or not after the  
'bytes' assignment is made (so we don't care if the compiler shortens  
the variable lifetime), so long as the memory pointed to by 'bytes'  
doesn't disappear too.


The consequence of this should be either:

(a) [data bytes] must promise to return a collectable object (so that  
the 'bytes' reference keeps it alive), or


(b) [data bytes] must lock (pseudo-retain) something internally  
(possibly just 'data' itself) and be matched with an unlock (pseudo- 
release) method.


(Maybe there's a 3rd option, but I can't think of it. Your custom  
allocator suggestion is more or less equivalent to (b), I think.)


Case (a) would be nice for programmers, but I assume it isn't  
implemented that way now for reasons of performance. Case (b) is  
annoying to use, especially if you went to a GC-app to avoid worrying  
about retain/release, but at least it's safe if coded correctly.


Since [data bytes] is neither (a) nor (b) right now, I'd suggest that  
the defect is in the NSData API. Personally, I'd prefer (a), since I  
never assumed anything about the performance of NSData allocations  
anyway.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread John Engelhart


On Jun 6, 2008, at 7:27 PM, Quincey Morris wrote:



On Jun 6, 2008, at 15:48, Bill Bumgarner wrote:

The garbage collector does not currently interpret inner pointers  
as something that can keep an encapsulating object alive.  Thus,  
the behavior is undefined and that it changes between debug and  
release builds -- between optimization levels of the compiler -- is  
neither surprising nor considered to be a bug.


Yes, it's certainly not the "inner" pointer's job to keep the object  
alive. I can't help feeling that it would make sense for the  
lifetime of the object pointer variable to be the same as its scope.  
(I have no idea if there's any language specification that deals  
with this.) If there's any compiler bug, it's the optimization that  
shortens the object pointer variable lifetime that's at fault.


In my personal experience, I've had so many problems when using  
Leopards GC system that I consider it to be 'unusable'.  This isn't  
meant as a slight against the GC team, as bolting GC on to a pre- 
existing and well establish C system is 'non-trivial', and that's an  
understatement.  It's also not any single issue or quirk, either, but  
the fact that they unintentionally conspire together to make the  
problems sum greater than its individual parts.


One recent programming project of mine is TransactionKit (http://transactionkit.sourceforge.net/ 
), which is a completely lockless multi-reader multi-writer hash  
table.  Complex lockless data structures and GC go hand in hand as GC  
neatly and cleanly solves the sticky issue of when it is safe to  
reclaim a piece of memory used to hold the tables data: keeping track  
of which threads are referencing a piece of the structure isn't  
simple, and freeing allocations while a thread is still using it has  
some obvious detrimental consequences.


Bill contacted me and asked about my problems.  In the end, I gave it  
another go.  However, the amount of work I sunk it to making things  
work so that it could run for minutes at a time without crashing was  
substantial, on the order of a solid week and a half.


Problems ranged from the mundane: The core is written in C for  
portability.  Pointers are tagged with a #define macro to selectively  
add __strong to them, so all the pointers in the C code were  
__strong.  You'd figure that turning GC on in Xcode and recompiling is  
all that it takes, since your pointers are properly marked as  
__strong.  Nope.  Since .c files are C (surprise!), Xcode doesn't pass  
the compiler -fobj-gc for these files.  However, you can still add  
__strong to pointers for 'C' files but it's silently discarded by the  
compiler.  The end result is that the unintended consequence of all  
these interactions is that you can easily be lulled in to thinking .c  
files are being properly compiled with GC support, and all your  
__strong tags are working.  On top of that, single one-shot tests will  
almost certainly execute flawlessly as a lot of individual tests  
aren't likely to trigger a collection.  The chances that you'll 'get  
lucky' and have something on the stack 'shadow cover' an allocation  
are also pretty high.  In my particular case the stress tests caused a  
virtually instantaneous crash and it only took a few minutes to figure  
out why.  The answer is that you can't add -fobjc-gc to .c files as  
that just results in a warning, you need to tell the compiler to treat  
the .c file as an objective-c .m file.


Other problems included a bug in the GC atomic CAS pointer swap  
function.  If you call objc_atomicCompareAndSwapGlobalBarrier() and  
the address where the CAS will take place is on the stack, libauto  
will fault as soon as that thread exits.  The reason it faults is that  
it attempts to read something from the old threads stack, but the  
threads stack has already been unmapped by the system and no longer  
exists.


Another quirk is that the compiler doesn't warn you when you  
'downcast' a __strong qualified pointer to a non-__strong qualified  
pointer.  I spent countless hours hunting down a single missed  
__strong qualification that was causing random crashes.  And the  
effects of missing a __strong qualification are completely  
unpredictable: some times the test suit would complete without  
crashing (taking a few minutes), other times it would crashing right  
after starting up.  The reason is because missing the __strong  
qualification turns it in to a race condition bug: some times you get  
lucky and never run in to the conditions which force it to become a  
problem, other times you run smack in to it.


Considering the fact that these tests were heavily multi-threaded and  
purpose built to stress test short lived objects that were handed off  
between threads via a central hash table makes you wonde

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 2:18 PM, Michael Ash <[EMAIL PROTECTED]> wrote:

> The business about scanning the stack is essentially an
> implementation detail; the promise that is being made is that objects
> which you're still pointing to won't go away.

We're just interpreting this promise differently. To my mind, while
the variable is still in scope, I *do* have a pointer to the object.
It is available for my use until the end of that scope. The fact that
I don't actually make use of it, and the optimising compiler thinks
I'm done with it: *that*'s an implementation detail.

> How would it be less straightforward? If it returned collected memory
> then everything will Just Work for the common case of using the
> pointer on the stack. You would also have the additional convenience
> of being able to safely store the returned pointer in a __strong heap
> variable, something which you simply cannot do under non-GC rules at
> all. Looks like there are only improvements to me, where is the
> problem?

I agree with you that if it returned collected memory, it would be
more powerful than under retain/release/autorelease. But power and
straightforwardness do not always go hand in hand ;)

> It *does* do this. The error is not in the GC, but rather in the
> assumption that "declared in the current scope" is equivalent to "is
> on the stack frame"

Again, I see that as an implementation detail. From the documentation:

"The root set is comprised of all objects reachable from root objects
and all possible references found by examining the call stacks of
every Cocoa thread."

Given that the programmer cannot possibly know the state of the call
stack any other way than by considering normal variable scoping rules,
either it's meaningless to consider any variable on the stack as a
root object, or the compiler needs to guarantee equivalence between
them.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Ricky Sharp


On Jun 7, 2008, at 8:18 AM, Michael Ash wrote:


It *does* do this. The error is not in the GC, but rather in the
assumption that "declared in the current scope" is equivalent to "is
on the stack frame". This assumption is not valid. The fact that you
can't make this assumption is extremely inconvenient for the situation
being discussed, but that doesn't mean that it's not behaving as
documented.



I did a double-take myself during the start of this thread and took a  
while for it all to sink in.  I completely agree with what Michael  
here and others have been pointing out.  Perhaps the following diagram  
and comparison to other code will be helpful to others:


- (void)foo
{
[1]NSData* data = [...];
[2]const unsigned char* bytes = [data bytes];
[3]while (condition)
[4]do work on bytes
[5]remaining code which does not operate on either data or bytes
}

Below, let || represent a short span of time that covers a  
particular line of code.  Fill it with # to denote timeframes where  
'data' is valid (i.e. cannot be collected).  Fill it with $ to denote  
timeframes where the GC thread can collect data.


1 2 3 4 5
Main Thread: |#|#|-|-|-|

GC Thread  : |-|-|$|$|$|


- (void)bar
{
[1]NSData* data = [...];
[2]const unsigned char* bytes = [data bytes];
[3]while (condition)
[4]do work on bytes
[5][data self];
[6]remaining code which does not operate on either data or bytes
}

1 2 3 4 5 6
Main Thread: |#|#|#|#|#|-|

GC Thread  : |-|-|-|-|-|$|


You can thus see that for each method, the GC thread can collect  
'data' at a point prior to the last statement.  Sometimes, as is  
'foo', this can be quite 'early'.




I haven't yet moved my app to GC since it's still baselined to 10.4.   
When I do migrate, I will have to tackle this specific NSData issue.   
For my needs, I'm hoping that a simple copy to a well-formed buffer  
will suffice.  Performance is not an issue and quantity of bytes is  
always small.


I will hope though that within the context of say memcpy, that the GC  
thread could not collect data.  For example, the following should be  
safe:


memcpy(myLocalGCAwareBuffer, [data bytes], numberOfBytes);


Finally, I think that usages of NSMutableData may also be a bit  
tricky.  In my case I'll probably just obtain a copy of its bytes,  
manipulate them and then copy the result back in. Sort of ironic  
though in that the inner pointer would have been valid anyhow in such  
blocks of code (the NSMutableData instance would be around between the  
get and subsequent set of its bytes):


NSMutableData* data = [...];
const unsigned char* bytes = [data bytes];
operate on copy of bytes in GC-aware buffer
[data replaceBytesInRange:...];

___
Ricky A. Sharp mailto:[EMAIL PROTECTED]
Instant Interactive(tm)   http://www.instantinteractive.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 8:47 AM, Hamish Allan <[EMAIL PROTECTED]> wrote:
> On Sat, Jun 7, 2008 at 12:34 PM, Michael Ash <[EMAIL PROTECTED]> wrote:
>
>> The problem here is
>> that you're expecting one pointer to keep a *different* pointer live,
>> which the GC does not make any guarantees about.
>
> Pre garbage collection, this was straightforward: as long as you
> retain your NSData, the pointer returned by [thatData bytes] is valid.
>
> Post garbage collection, you would expect the rule to be equivalent:
> as long as you have a strong reference to your NSData, the pointer
> returned by [thatData bytes] is valid.
>
> Until the stack frame is popped, you have a strong reference to your
> NSData. Unless of course the compiler thinks it knows better. But I
> agree with Ken: the compiler is wrong.

What I'm saying is that the compiler+GC only guarantees that you have
a strong reference to that object *while you're using it*. It's very
easy to take the documentation and make a small leap to say that you
have a strong reference to an object for as long as the function where
the pointer is declared is on the stack, but that's not actually what
it says. The business about scanning the stack is essentially an
implementation detail; the promise that is being made is that objects
which you're still pointing to won't go away. Once you pass the last
reference to an object, all bets are off.

>> Basically, under GC, my impression is that it should be considered
>> invalid to return a pointer to a caller which depends on the lifetime
>> of the parent object. In this case, for example, NSData really should
>> be returning a pointer to collected memory, so that instead of having
>> to pull dirty tricks to keep the NSData pointer alive, you can just
>> pull regular easy tricks to keep the char * pointer alive.
>
> Even if the NSData returned collected memory, it would still be less
> straightforward to use GC than pre-GC memory management. I thought GC
> was supposed to make memory management easier?!

How would it be less straightforward? If it returned collected memory
then everything will Just Work for the common case of using the
pointer on the stack. You would also have the additional convenience
of being able to safely store the returned pointer in a __strong heap
variable, something which you simply cannot do under non-GC rules at
all. Looks like there are only improvements to me, where is the
problem?

> All we really need is for the GC to behave as documented: treat an
> object whose variable is on the stack frame as a root object.

It *does* do this. The error is not in the GC, but rather in the
assumption that "declared in the current scope" is equivalent to "is
on the stack frame". This assumption is not valid. The fact that you
can't make this assumption is extremely inconvenient for the situation
being discussed, but that doesn't mean that it's not behaving as
documented.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 12:34 PM, Michael Ash <[EMAIL PROTECTED]> wrote:

> The problem here is
> that you're expecting one pointer to keep a *different* pointer live,
> which the GC does not make any guarantees about.

Pre garbage collection, this was straightforward: as long as you
retain your NSData, the pointer returned by [thatData bytes] is valid.

Post garbage collection, you would expect the rule to be equivalent:
as long as you have a strong reference to your NSData, the pointer
returned by [thatData bytes] is valid.

Until the stack frame is popped, you have a strong reference to your
NSData. Unless of course the compiler thinks it knows better. But I
agree with Ken: the compiler is wrong.

> Basically, under GC, my impression is that it should be considered
> invalid to return a pointer to a caller which depends on the lifetime
> of the parent object. In this case, for example, NSData really should
> be returning a pointer to collected memory, so that instead of having
> to pull dirty tricks to keep the NSData pointer alive, you can just
> pull regular easy tricks to keep the char * pointer alive.

Even if the NSData returned collected memory, it would still be less
straightforward to use GC than pre-GC memory management. I thought GC
was supposed to make memory management easier?!

> The problem with this is that it's incompatible with the idea of
> wrapping different types of pointers, such as memory mapped files.
> That's why I refer to it as a design flaw rather than a simple bug to
> fix.
>
> Unfortunately I don't know what the solution would be. Under the
> old-style rules, the lifetime for an NSData object would be fairly
> predictable (previous examples in this thread have brought up release
> messages being sent by other threads, but this would be wholly invalid
> usage to begin with) thus it was safe to work with a pointer whose
> lifetime was completely tied to it. Now the lifetime is not
> predictable in the general case, even if you do everything else right,
> so you have to work to make it be predictable.

All we really need is for the GC to behave as documented: treat an
object whose variable is on the stack frame as a root object.

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 12:42 AM, Bill Bumgarner <[EMAIL PROTECTED]> wrote:

> The easiest way to do this is to simply to use data once after the for()
> loop:
>
>NSData* data = ;
>const unsigned char* bytes = [data bytes];
>NSUInteger count = [data length];
>for (NSUInteger i = 0; i < count; i++)
>something = bytes [i];
>[data self];

What about using the __strong modifier? The compiler surely won't
consider "bytes" to be collectable until after the loop.

NSData* data = ;
__strong const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Hamish Allan
On Sat, Jun 7, 2008 at 12:31 AM, Bill Bumgarner <[EMAIL PROTECTED]> wrote:

> Yes, it is an exceedingly important optimization.  Most likely, that stack
> slot is being reused by some variable later on.

I can see how this might be "exceedingly important" for deeply
recursive functions, but for the common case? Do the benefits really
outweigh the problems?

Hamish
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Michael Ash
On Sat, Jun 7, 2008 at 7:13 AM, Ken Thomases <[EMAIL PROTECTED]> wrote:
> Nobody is claiming that it should.  It's not about the char* pointer.  It's
> about the NSData* pointer.

Actually I think that it is about the char * pointer, and this bug
should be considered an NSData bug rather than a compiler bug or a GC
bug. The fact that it's really a design bug in NSData rather than
something that can be easily fixed definitely makes it worse, but
doesn't really change the location of the fault.

The GC basically guarantees you that objects which you continue to use
will continue to live until you're finished using them. Optimizations
don't affect this at all; the compiler can't optimize away the storage
of an object pointer until you're done using it. The problem here is
that you're expecting one pointer to keep a *different* pointer live,
which the GC does not make any guarantees about.

Basically, under GC, my impression is that it should be considered
invalid to return a pointer to a caller which depends on the lifetime
of the parent object. In this case, for example, NSData really should
be returning a pointer to collected memory, so that instead of having
to pull dirty tricks to keep the NSData pointer alive, you can just
pull regular easy tricks to keep the char * pointer alive.

The problem with this is that it's incompatible with the idea of
wrapping different types of pointers, such as memory mapped files.
That's why I refer to it as a design flaw rather than a simple bug to
fix.

Unfortunately I don't know what the solution would be. Under the
old-style rules, the lifetime for an NSData object would be fairly
predictable (previous examples in this thread have brought up release
messages being sent by other threads, but this would be wholly invalid
usage to begin with) thus it was safe to work with a pointer whose
lifetime was completely tied to it. Now the lifetime is not
predictable in the general case, even if you do everything else right,
so you have to work to make it be predictable.

Perhaps the solution would be for the GC to allow for collected memory
with a custom allocator. This way NSData could always make the
internal memory be collected, using the custom allocator to properly
clean up for cases such as memory mapped files.

Mike
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Ken Thomases

On Jun 7, 2008, at 3:41 AM, Quincey Morris wrote:


On Jun 7, 2008, at 00:07, Antonio Nunes wrote:

Although I maybe did not make it that clear, I actually meant my  
suggestion also as a question. I'm surprised no-one else suggested  
to temporarily turn of garbage collection for this pointer. I'm  
curious as to why Bill suggested his solution rather than directly  
instructing the garbage collector, since that would seem to me the  
more obvious solution. Is Bill's solution preferable in any way?  
(After all, I'd like to improve to the level where I know what I'm  
doing ;-)


I can think of one significant difference. Using CFRetain/CFRelease  
(or your slightly more general equivalent) is a procedural solution  
-- you would need to make sure there was a matching release on every  
execution path out of the relevant code.


Including in the face of exceptions.

-Ken

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Ken Thomases

On Jun 7, 2008, at 12:03 AM, Bill Bumgarner wrote:


On Jun 6, 2008, at 9:16 PM, Ken Thomases wrote:

And... we're back to retain/release.
The issue is, how can one know when this technique is necessary?   
The supposed rules of GC are, if it's in a stack variable, it's  
safe.  The compiler here is doing something behind the programmer's  
back, which the programmer can't really predict, that's changing  
the rules.


Quoting the Garbage Collection Programming Guide: "The initial root  
set of objects is comprised of global variables, stack variables,  
and objects with external references. These objects are never  
considered as garbage"


For some values of "never".

Objective-C 2.0's garbage collection system is incompatible with  
any optimization which changes which variables are on the stack.   
More accurately, it's an error if compiler optimizations change  
what are considered root objects.


The problem here is that there is no way for the compiler to know  
that the char* bytes is somehow connected to the lifespan of the  
NSData*.  Nor is there any way for the collector to know that the  
char* bytes is somehow an implied root of the NSData* object.


Nobody is claiming that it should.  It's not about the char* pointer.   
It's about the NSData* pointer.



The compiler isn't changing roots and it isn't doing anything that  
is a bug


It is and it is, depending on the meaning of "on the stack".  See below.

-- it is merely optimizing the code to use the resources available  
by recycling bits of memory that refer to items that, given all  
knowledge that it has, are no longer needed.


I disagree.  The problem is that there are two possible meanings of  
"on the stack".  In the sense that the GC system means, the phrase is  
effectively meaningless.  It's discussing details of the emitted  
object code, which the programmer has no clear way of anticipating  
with the current compiler, let alone future compilers.


What the programmer can see, and what s/he can control, is the scope  
of automatic local variables.  Many programmers probably assume that's  
what the GC documentation means -- that if a variable is in scope,  
then it's in the root set.  Evidently, that's not what it means.  You  
could argue that means the programmer is mistaken.  I argue that means  
that the design of the GC system or of the compiler is, uh, less than  
perfect.  As things stand, programmers have to defensively apply  
"voodoo" code practices (e.g. adding otherwise unnecessary [data self]  
calls) to avoid unpredictable results.


This is exacerbated by the fact that the NSData* _is_ on the stack so  
long as optimizations are turned off, but isn't when they're turned  
on.  Turning on optimizations should not change the correctness of code.


The GC system rules need to be not just technically accurate, but  
offer practical guidance to programmers that doesn't require them to  
understand what the compiler is doing or might do.  "Practical" as in  
"may be put into practice".  Guidance about variable scope is  
practical.  Guidance about characteristics of the emitted object code  
is not, in my opinion.


Regards,
Ken
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Quincey Morris


On Jun 7, 2008, at 00:07, Antonio Nunes wrote:

Although I maybe did not make it that clear, I actually meant my  
suggestion also as a question. I'm surprised no-one else suggested  
to temporarily turn of garbage collection for this pointer. I'm  
curious as to why Bill suggested his solution rather than directly  
instructing the garbage collector, since that would seem to me the  
more obvious solution. Is Bill's solution preferable in any way?  
(After all, I'd like to improve to the level where I know what I'm  
doing ;-)


I can think of one significant difference. Using CFRetain/CFRelease  
(or your slightly more general equivalent) is a procedural solution --  
you would need to make sure there was a matching release on every  
execution path out of the relevant code.


Using something like '[data self]' is a syntactic solution. It doesn't  
matter whether it gets executed or not, but its mere presence far  
enough down the source code is all that's required.


Depending on the circumstances, one or other approach might be  
preferred.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-07 Thread Quincey Morris
I'm fairly satisfied with Bill's (and others') suggested workarounds  
about how to keep the object from being collected, but if I might  
ramble just a little:



On Jun 6, 2008, at 22:03, Bill Bumgarner wrote:


On Jun 6, 2008, at 9:16 PM, Ken Thomases wrote:

And... we're back to retain/release.
The issue is, how can one know when this technique is necessary?   
The supposed rules of GC are, if it's in a stack variable, it's  
safe.  The compiler here is doing something behind the programmer's  
back, which the programmer can't really predict, that's changing  
the rules.


I agree that the important part is that "the programmer can't really  
predict". You have to scrutinize the source to see the places where  
the compiler *might* optimize a variable lifetime. And remember to do  
it.


Quoting the Garbage Collection Programming Guide: "The initial root  
set of objects is comprised of global variables, stack variables,  
and objects with external references. These objects are never  
considered as garbage"


Given my understanding of the words involved here, this quoted  
statement is nonsensical if taken literally. Objects (in the sense of  
memory blocks known to the GC) are not the same as variables. There  
are no variables in the initial root set of objects, only objects.  
Presumably, what is meant is "objects whose pointers are currently  
held in global variables and stack variables". I also never understood  
what "objects with external references" meant. Are they objects with  
external references *to* them from somewhere else? That sounds like  
global variables again. Or objects with references to other objects?  
Why would that in itself put the referring objects in the initial root  
set, and why would those references need to be called "external"?


Further, AFAIK, the reference to "stack variables" just isn't true. If  
I understand the clues in posts made here over the past months, it's  
got nothing to do with variables. The GC simply (AFAIK) scans all  
"live" areas of the stack for pointer-sized values that look like GC- 
managed object pointers, and adds those objects to the initial root  
set. (Ditto for registers, I assume, though I don't recall that being  
mentioned.) The compiler (AFAIK) doesn't emit any code or information  
to identify object pointer variable addresses, or to manage object  
lifetimes (except for object references via pointers held in instance  
variables, but that's a different matter). If you put a numerical  
value into an int stack variable that happens to be the bit pattern of  
some GC object address, it will (AFAIK) count as a root reference that  
will keep the object from being collected.



For some values of "never".

Objective-C 2.0's garbage collection system is incompatible with  
any optimization which changes which variables are on the stack.   
More accurately, it's an error if compiler optimizations change  
what are considered root objects.


I wouldn't say "which variables are on the stack", but rather "which  
stack variables are live at any given point in the source code". For  
example, at the end of the method's (outermost) scope, all its stack  
variables are no longer live.


Clearly, it's incorrect for a compiler optimization to cause a change  
of the value at a stack address used by a live variable, but that's  
not happening here.


So it's more a question of whether it's an error for a compiler  
optimization to change the lifetime of a variable. Bill's answer is,  
"No, because the lifetime of a variable is by definition whatever the  
compiler chooses to make it after optimizing."


(And, of course, the lifetime of a variable is something entirely  
different from the lifetime of an object.)


The problem here is that there is no way for the compiler to know  
that the char* bytes is somehow connected to the lifespan of the  
NSData*.  Nor is there any way for the collector to know that the  
char* bytes is somehow an implied root of the NSData* object.


The compiler isn't changing roots and it isn't doing anything that  
is a bug -- it is merely optimizing the code to use the resources  
available by recycling bits of memory that refer to items that,  
given all knowledge that it has, are no longer needed.


There is actually no guarantee that the -bytes method will return a  
reference to a malloc'd block of data;  it may return an arbitrary  
pointer into some other Data's hunk of data.


This is an edge case.   It is uncommon and the kind of edge case  
that only exists when you dip below Objective-C and into the realm  
of C.


It seems to me that the consequence of working around this issue is  
that every scope in which a NSData* variable is declared must be  
carefully examined for variable lifetime issues (or a '[data self]'- 
style sentinel routinely placed at the end of every such scope). EVERY  
scope. Given the central role that NSData plays in Cocoa file I/O and  
Core Data (to name a couple of really obvious

Re: Garbage collector vs variable lifetime

2008-06-07 Thread Antonio Nunes

On 7 Jun 2008, at 06:16, Ken Thomases wrote:


On Jun 6, 2008, at 10:48 PM, Antonio Nunes wrote:

Why not explicitly turn off collection for the data pointer:

NSData* data = ;
[[NSGarbageCollector defaultCollector]  
disableCollectorForPointer:data];

const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[[NSGarbageCollector defaultCollector]  
enableCollectorForPointer:data];


It's slightly longer, but straightforward and clear about it's  
purpose, and should be future proof.


And... we're back to retain/release. [...]
The issue is, how can one know when this technique is necessary?


By proper documentation. As Bill mentioned earlier, the documentation  
needs to mention this behaviour. Just as retain/release, GC has its  
own caveats, it's own moments where one has to take special care. This  
appears to be one of them. If I read Bill's explanation correctly then  
once the documentation gets updated and distributed anyone can know  
when this technique is necessary (as long as they know what they're  
doing, which goes for anything in programming).


On 7 Jun 2008, at 07:03, Bill Bumgarner wrote:
The problem here is that there is no way for the compiler to know  
that the char* bytes is somehow connected to the lifespan of the  
NSData*.  Nor is there any way for the collector to know that the  
char* bytes is somehow an implied root of the NSData* object. [etc...]
This is an edge case.   It is uncommon and the kind of edge case  
that only exists when you dip below Objective-C and into the realm  
of C.


Although I maybe did not make it that clear, I actually meant my  
suggestion also as a question. I'm surprised no-one else suggested to  
temporarily turn of garbage collection for this pointer. I'm curious  
as to why Bill suggested his solution rather than directly instructing  
the garbage collector, since that would seem to me the more obvious  
solution. Is Bill's solution preferable in any way? (After all, I'd  
like to improve to the level where I know what I'm doing ;-)


-António

-
Perfume is the forgiveness
that the trampled flower casts
upon the heel that crushes it.
-



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Bill Bumgarner

On Jun 6, 2008, at 9:16 PM, Ken Thomases wrote:

And... we're back to retain/release.
The issue is, how can one know when this technique is necessary?   
The supposed rules of GC are, if it's in a stack variable, it's  
safe.  The compiler here is doing something behind the programmer's  
back, which the programmer can't really predict, that's changing the  
rules.


Quoting the Garbage Collection Programming Guide: "The initial root  
set of objects is comprised of global variables, stack variables,  
and objects with external references. These objects are never  
considered as garbage"


For some values of "never".

Objective-C 2.0's garbage collection system is incompatible with any  
optimization which changes which variables are on the stack.  More  
accurately, it's an error if compiler optimizations change what are  
considered root objects.


The problem here is that there is no way for the compiler to know that  
the char* bytes is somehow connected to the lifespan of the NSData*.   
Nor is there any way for the collector to know that the char* bytes is  
somehow an implied root of the NSData* object.


The compiler isn't changing roots and it isn't doing anything that is  
a bug -- it is merely optimizing the code to use the resources  
available by recycling bits of memory that refer to items that, given  
all knowledge that it has, are no longer needed.


There is actually no guarantee that the -bytes method will return a  
reference to a malloc'd block of data;  it may return an arbitrary  
pointer into some other Data's hunk of data.


This is an edge case.   It is uncommon and the kind of edge case that  
only exists when you dip below Objective-C and into the realm of C.


b.bum









smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-06 Thread Ken Thomases

On Jun 6, 2008, at 10:48 PM, Antonio Nunes wrote:


On 7 Jun 2008, at 01:42, Bill Bumgarner wrote:

The easiest way to do this is to simply to use data once after the  
for() loop:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[data self];

Yup.  I don't particularly like it either.  Fortunately, it is an  
uncommon case -- most of the objects in the AppKit/Foundation "just  
work".   This kind of a problem arises when something leverages the  
C in Objective-C.


Quincey Morris wrote:
A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


Why not explicitly turn off collection for the data pointer:

NSData* data = ;
[[NSGarbageCollector defaultCollector]  
disableCollectorForPointer:data];

const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[[NSGarbageCollector defaultCollector]  
enableCollectorForPointer:data];


It's slightly longer, but straightforward and clear about it's  
purpose, and should be future proof.


And... we're back to retain/release.

The issue is, how can one know when this technique is necessary?  The  
supposed rules of GC are, if it's in a stack variable, it's safe.  The  
compiler here is doing something behind the programmer's back, which  
the programmer can't really predict, that's changing the rules.


Quoting the Garbage Collection Programming Guide: "The initial root  
set of objects is comprised of global variables, stack variables, and  
objects with external references. These objects are never considered  
as garbage"


For some values of "never".

Objective-C 2.0's garbage collection system is incompatible with any  
optimization which changes which variables are on the stack.  More  
accurately, it's an error if compiler optimizations change what are  
considered root objects.


Regards,
Ken
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Bill Bumgarner

On Jun 6, 2008, at 5:36 PM, Quincey Morris wrote:
Thanks, and to Shawn for the same suggestion. It's a pragmatic  
solution I can deal with.
A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
NSUInteger largestByte = 0;
for (NSUInteger i = 0; i < count; i++)
largestByte = MAX (largestByte , bytes [i]);
[data self];

TBH, I don't see any real solution without making the compiler aware  
of the GC consequences of its optimizations.


In this case, that wouldn't be a GC issue.   Every invocation of an  
Objective-C -- every Obj-C call site -- is dynamically bound and,  
thus, dynamically dispatched.   Thus, the call site can't be moved  
without risk that the application behavior will change.


For example, it would be possible to cause the above to change what  
[data self] means when a particular bytes[i] is read.


b.bum



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-06 Thread Antonio Nunes

On 7 Jun 2008, at 01:42, Bill Bumgarner wrote:

The easiest way to do this is to simply to use data once after the  
for() loop:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[data self];

Yup.  I don't particularly like it either.  Fortunately, it is an  
uncommon case -- most of the objects in the AppKit/Foundation "just  
work".   This kind of a problem arises when something leverages the  
C in Objective-C.


Quincey Morris wrote:
A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


Why not explicitly turn off collection for the data pointer:

NSData* data = ;
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:data];
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[[NSGarbageCollector defaultCollector] enableCollectorForPointer:data];

It's slightly longer, but straightforward and clear about it's  
purpose, and should be future proof.


António


It isn't so important to do great things,
as to do what you do with great love.




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread George Stuart

On Jun 6, 2008, at 7:05 PM, Ricky Sharp wrote:



On Jun 6, 2008, at 6:42 PM, Bill Bumgarner wrote:



Sorry -- let me clarify.   If the  was either released in a  
different thread or if  were explicitly released in the above  
code, then you would see the same crash.   I didn't mean to imply  
that  would be released under non-GC without some explicit  
action being taken.


Under GC, the situation isn't quite so clear.



That makes perfect sense.  Sorry that I glossed over the 'other  
thread' bit.




What about using the data pointer directly in the loop?  Would this  
prevent the GC thread from freeing that memory early?  This sends a  
message to the data object at each iteration, so not as optimal as  
pointer arithmetic I suppose...


NSData* data = ;
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
[data getBytes:&something range:NSMakeRange(i, 1)];

Cheers,
George
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Quincey Morris


On Jun 6, 2008, at 16:42, Bill Bumgarner wrote:

The easiest way to do this is to simply to use data once after the  
for() loop:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[data self];

Yup.  I don't particularly like it either.  Fortunately, it is an  
uncommon case -- most of the objects in the AppKit/Foundation "just  
work".   This kind of a problem arises when something leverages the  
C in Objective-C.


Thanks, and to Shawn for the same suggestion. It's a pragmatic  
solution I can deal with.


A little inner voice insists on asking, though, how we know some  
future version of the compiler might not optimize '[data self]'  
upwards before the loop, if it decides that nothing inside the loop  
references anything non-local:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
NSUInteger largestByte = 0;
for (NSUInteger i = 0; i < count; i++)
largestByte = MAX (largestByte , bytes [i]);
[data self];

TBH, I don't see any real solution without making the compiler aware  
of the GC consequences of its optimizations.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Ricky Sharp


On Jun 6, 2008, at 6:42 PM, Bill Bumgarner wrote:



Sorry -- let me clarify.   If the  was either released in a  
different thread or if  were explicitly released in the above  
code, then you would see the same crash.   I didn't mean to imply  
that  would be released under non-GC without some explicit  
action being taken.


Under GC, the situation isn't quite so clear.



That makes perfect sense.  Sorry that I glossed over the 'other  
thread' bit.


___
Ricky A. Sharp mailto:[EMAIL PROTECTED]
Instant Interactive(tm)   http://www.instantinteractive.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Clark Cox
On Fri, Jun 6, 2008 at 4:27 PM, Quincey Morris
<[EMAIL PROTECTED]> wrote:
>
> On Jun 6, 2008, at 15:48, Bill Bumgarner wrote:
>
>> In any case, you need to make sure that  stays alive throughout the
>> entire lifespan of the bytes pointer.
>
> But the puzzling question is: how?

CFRetain/CFRelease will do the trick if needed.

-- 
Clark S. Cox III
[EMAIL PROTECTED]
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Bill Bumgarner

On Jun 6, 2008, at 4:24 PM, Ricky Sharp wrote:

On Jun 6, 2008, at 5:48 PM, Bill Bumgarner wrote:

On Jun 6, 2008, at 3:23 PM, Quincey Morris wrote:

In a GC-only app, I frequently use a pattern along these lines:

NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];

In any case, you need to make sure that  stays alive  
throughout the entire lifespan of the bytes pointer.  This is no  
different than in non-GC.  If  were released sometime before  
the for loop were done, a similar crash would occur.
I'm a bit confused by this.  In non-GC, data would not be released  
during the loop execution.  Let's assume that it was autoreleased  
during the 'get it from somewhere'.  It would only be actually  
released when execution returns to the main run loop; clearly after  
the entire loop above would be executed.


Sorry -- let me clarify.   If the  was either released in a  
different thread or if  were explicitly released in the above  
code, then you would see the same crash.   I didn't mean to imply that  
 would be released under non-GC without some explicit action  
being taken.


Under GC, the situation isn't quite so clear.

On Jun 6, 2008, at 4:27 PM, Quincey Morris wrote:
But the puzzling question is: how? Anything involving stack  
variables could potentially be optimized away. I could move the  
collectable object pointer into a global or instance variable, but  
that solution comes unglued as soon as I hit a case where the  
containing method is called recursively. I suppose a file static  
NSMutableSet temporarily holding collectable objects would work.


Good question.   The easiest way is to force the compiler to maintain  
a viable reference to  on the stack throughout the code that is  
using gunk from inside of .  There is no way for the compiler or  
-- reliably, the collector, at this time-- to know that  is  
somehow connected to the storage of  and, thus, you need to make  
sure  stays alive.


The easiest way to do this is to simply to use data once after the  
for() loop:


NSData* data = ;
const unsigned char* bytes = [data bytes];
NSUInteger count = [data length];
for (NSUInteger i = 0; i < count; i++)
something = bytes [i];
[data self];

Yup.  I don't particularly like it either.  Fortunately, it is an  
uncommon case -- most of the objects in the AppKit/Foundation "just  
work".   This kind of a problem arises when something leverages the C  
in Objective-C.


This is an area where the collector will hopefully be able to improve  
upon the coding experience in future releases.


b.bum



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-06 Thread Shawn Erickson
On Fri, Jun 6, 2008 at 4:27 PM, Quincey Morris
<[EMAIL PROTECTED]> wrote:

> But the puzzling question is: how?

Send a message to the NSData object after the block is done with the
byte pointer. ([data self])

-Shawn
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Bill Bumgarner

On Jun 6, 2008, at 4:18 PM, Hamish Allan wrote:

On Fri, Jun 6, 2008 at 11:48 PM, Bill Bumgarner <[EMAIL PROTECTED]> wrote:

The garbage collector does not currently interpret inner pointers as
something that can keep an encapsulating object alive.

But it's not the inner pointers I would expect to keep the object
alive -- it's the fact that stack variables are root objects, and that
NSData *data is still in the current stack frame.

Fromhttp://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcEssentials.html
:

"The initial root set of objects is comprised of global variables,
stack variables, and objects with external references. These objects
are never considered as garbage. The root set is comprised of all
objects reachable from root objects and all possible references found
by examining the call stacks of every Cocoa thread."

If the optimising compiler is marking variables past a certain point
in the code block as being collectable because it doesn't think
they're going to be used again before the stack frame is popped, this
should be made explicit in the documentation (perhaps it is but I
missed it).

And is it really that important of an optimisation to make, if it's
going to have side effects like this?


Yes, it is an exceedingly important optimization.  Most likely, that  
stack slot is being reused by some variable later on.


I filed a bug asking that particular doc to be clarified-- >-- I can't remember if it is mentioned anywhere else, but it should  
definitely be mentioned there!


b.bum






smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Re: Garbage collector vs variable lifetime

2008-06-06 Thread Nick Zitzmann


On Jun 6, 2008, at 5:24 PM, Ricky Sharp wrote:

I'm a bit confused by this.  In non-GC, data would not be released  
during the loop execution.  Let's assume that it was autoreleased  
during the 'get it from somewhere'.  It would only be actually  
released when execution returns to the main run loop; clearly after  
the entire loop above would be executed.



In GC, all collection goes on in a separate thread, which is why data  
can be released during a loop.


Nick Zitzmann


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


Re: Garbage collector vs variable lifetime

2008-06-06 Thread Quincey Morris


On Jun 6, 2008, at 15:48, Bill Bumgarner wrote:

The garbage collector does not currently interpret inner pointers as  
something that can keep an encapsulating object alive.  Thus, the  
behavior is undefined and that it changes between debug and release  
builds -- between optimization levels of the compiler -- is neither  
surprising nor considered to be a bug.


Yes, it's certainly not the "inner" pointer's job to keep the object  
alive. I can't help feeling that it would make sense for the lifetime  
of the object pointer variable to be the same as its scope. (I have no  
idea if there's any language specification that deals with this.) If  
there's any compiler bug, it's the optimization that shortens the  
object pointer variable lifetime that's at fault.


In any case, you need to make sure that  stays alive  
throughout the entire lifespan of the bytes pointer.


But the puzzling question is: how? Anything involving stack variables  
could potentially be optimized away. I could move the collectable  
object pointer into a global or instance variable, but that solution  
comes unglued as soon as I hit a case where the containing method is  
called recursively. I suppose a file static NSMutableSet temporarily  
holding collectable objects would work.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]


  1   2   >