Hi Ben,

Have you considered the so-called Flyweight design pattern? It is designed to 
solve the problem of having a zillion objects to allocate. It sounds like this 
pattern might prevent your having to play the dirty tricks that are causing you 
problems.

In the frameworks, Flyweight is used, AFAIK, in NSNumber, NSCell, and other 
classes. There's a good description of the pattern here:
http://en.wikipedia.org/wiki/Flyweight_pattern

Hope this helps a little. (I don't know what could be done to solve the crash 
you describe but passing pointers as you described sounds like it's bound to 
cause nasty problems.)

Soong



----- Original Message ----
From: Ben Haller <bhcocoa...@sticksoftware.com>
To: Cocoa List <cocoa-dev@lists.apple.com>
Sent: Thu, October 15, 2009 3:54:11 PM
Subject: GC crash due to being naughty

  Hi all.  I'm getting a crash in auto_zone_root_write_barrier() that I don't 
understand.  I suspect it has to do with this little blurb in the Garbage 
Collection Programming Guide:

Limitations on Mac OS X v10.5:  You may pass addresses of strong globals or 
statics into routines expecting
pointers to object pointers (such as id* or NSError**) only if they have first 
been assigned to directly, rather
than through a pointer dereference. You should never take the address of a weak 
global, static or instance
variable, as assigning or reading through that pointer will bypass the weak 
barriers and expose your programs
to race conditions.

  But I'm not really sure.  :->  Here's the situation.  My app generates floods 
of instances of an NSObject subclass called AKIndividual.  So many, in fact, 
that I don't want to alloc and dealloc them all, as that just thrashes the 
allocator madly (as verified with Sampler).  Instead, I want to allocate a pool 
of them, and then throw them in the pool when I'm done with them, and get new 
ones out of the pool.  (When I reuse them, I don't call -init again, I just 
wipe the ivars I'm using and put new values in, which I believe is OK.)  When 
I'm messing about with them, and when they're in the pool, I don't want to keep 
them in Cocoa collections like NSMutableArray, because again that introduces 
too much overhead.  Countless billions upon billions of these little guys I'm 
making, and the runtimes of my app will be measured in days to weeks, so 
optimizing this bottleneck really is important.

  So my solution was to keep pointers to them in malloced buffers instead.  The 
"unused pool" is a malloced buffer, the pools of ones that are doing various 
things are also malloced buffers, and everything is nice fast C code at this 
level.  But I guess pointers to objects kept in malloced buffers are weak 
references, so my objects would be collected if I didn't have a strong 
reference somewhere.  So when I first allocate them, I throw them into an 
NSMutableArray, and I don't ever take them out.  That array is kept by the 
controller of the whole shebang; so when that controller gets collected, then 
all the individuals will be collected, but until then, they should always be 
strong-referenced.

  This seems like it ought to work; and yet I get that crash in 
auto_zone_root_write_barrier().  After some puzzling, I found the above 
paragraph in the GC guide.  I am indeed on 10.5.  Is this what's biting me?  I 
guess all the pointers to my AKIndividuals that are kept in my malloced arrays 
are all weak references, and so I guess the pointer to the malloced array 
itself, for example, is a pointer to a weak reference such as I am not supposed 
to use, and whenever I do something like "individuals[i]" to get an instance 
from my malloced buffer I guess I'm violating the weak barriers.  I find it 
hard to believe that I'm not allowed to keep an array of pointers to objects, 
though; is that really what this blurb is saying?  (On the other hand, the GC 
guide also says that "the malloc zone is never scanned", which would imply that 
this is fine, and that the references I put in my malloced arrays are not even 
weak; but then I'm puzzled by the crash in a write
 barrier function...)  I don't really understand what is prohibited and exactly 
why; that blurb is way too short, and the example is too short and cryptic.  
Can some explain what is actually prohibited, and why, and whether what I'm 
doing is prohibited?

  Given the architecture I'm aiming for, I don't need the references to even be 
weak references; I don't need them to zero out, because they never will, 
because these AKIndividuals live at least as long as any given malloced array 
of them will live.  Indeed, I don't care about GC on them at all; I'd be quite 
happy to exclude them from the GC scheme altogether, and get back the overhead 
of these read/write barriers, given how much thrash is involved with them.  Is 
that possible?  For example, can I malloc the instances of AKIndividual myself 
out of the malloc zone to exclude them from GC, or is that a Bad Idea?

  Sorry for the long email.  Comments?

Ben Haller
Stick Software

_______________________________________________

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/oftenwrongsoong%40yahoo.com

This email sent to oftenwrongso...@yahoo.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

Reply via email to