From patchwork Mon Oct 4 19:06:23 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 66717 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id E1905B70DA for ; Tue, 5 Oct 2010 06:06:41 +1100 (EST) Received: (qmail 12538 invoked by alias); 4 Oct 2010 19:06:38 -0000 Received: (qmail 12528 invoked by uid 22791); 4 Oct 2010 19:06:37 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL, BAYES_00, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 04 Oct 2010 19:06:28 +0000 Received: from eggs.gnu.org ([140.186.70.92]:53541) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P2qMk-0002TL-5J for gcc-patches@gnu.org; Mon, 04 Oct 2010 15:06:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P2qMi-0001EN-8b for gcc-patches@gnu.org; Mon, 04 Oct 2010 15:06:26 -0400 Received: from smtp161.iad.emailsrvr.com ([207.97.245.161]:43773) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P2qMi-0001ED-4y for gcc-patches@gnu.org; Mon, 04 Oct 2010 15:06:24 -0400 Received: from relay16.relay.iad.mlsrvr.com (localhost [127.0.0.1]) by relay16.relay.iad.mlsrvr.com (SMTP Server) with ESMTP id 714681B4192; Mon, 4 Oct 2010 15:06:23 -0400 (EDT) Received: from dynamic9.wm-web.iad.mlsrvr.com (dynamic9.wm-web.iad.mlsrvr.com [192.168.2.216]) by relay16.relay.iad.mlsrvr.com (SMTP Server) with ESMTP id 671D81B417D; Mon, 4 Oct 2010 15:06:23 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic9.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id 57EB3320088; Mon, 4 Oct 2010 15:06:23 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Mon, 4 Oct 2010 21:06:23 +0200 (CEST) Date: Mon, 4 Oct 2010 21:06:23 +0200 (CEST) Subject: Re: ObjC fast enumeration documentation From: "Nicola Pero" To: "Ralf Wildenhues" Cc: gcc-patches@gnu.org MIME-Version: 1.0 X-Type: plain In-Reply-To: <20101004180106.GE24697@gmx.de> References: <1286190424.065729806@192.168.2.227> <20101004180106.GE24697@gmx.de> Message-ID: <1286219183.355628304@192.168.2.231> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Ralf, thanks for the tips. In attach a patch that addresses your points. :-) Is the patch attached correctly (not as binary) ? Thanks -----Original Message----- From: "Ralf Wildenhues" Sent: Monday, 4 October, 2010 20:01 To: "Nicola Pero" Cc: gcc-patches@gnu.org Subject: Re: ObjC fast enumeration documentation Hello Nicola, * Nicola Pero wrote on Mon, Oct 04, 2010 at 01:07:04PM CEST: > Documentation for ObjC fast enumeration. > > Ok to apply [once fast enumeration has been committed ;-)] ? Please don't attach patches as binary, that prevents easy quoting and commenting-upon in replies. > 2010-10-04 Nicola Pero > > * doc/objc.texi: Document fast enumeration. Things you write as > @code{} should be @code{@var{collection-expression}} instead; IOW, use @var{X} for metasyntactic variables X, not . Thanks, Ralf Index: objc.texi =================================================================== --- objc.texi (revision 164952) +++ objc.texi (working copy) @@ -20,6 +20,7 @@ several resources on the Internet that present the * compatibility_alias:: * Exceptions:: * Synchronization:: +* Fast enumeration:: @end menu @node Executing code before main @@ -739,3 +740,220 @@ Because of the interactions between synchronizatio handling, you can only use @code{@@synchronized} when compiling with exceptions enabled, that is with the command line option @option{-fobjc-exceptions}. + + +@c ========================================================================= +@node Fast enumeration +@section Fast enumeration + +@menu +* Using fast enumeration:: +* c99 fast enumeration syntax:: +* Fast enumeration details:: +* Fast enumeration protocol:: +@end menu + +@c ================================ +@node Using fast enumeration +@subsection Using fast enumeration + +GNU Objective-C provides support for the fast enumeration syntax: + +@smallexample + id array = @dots{}; + id object; + + for (object in array) + @{ + /* Do something with 'object' */ + @} +@end smallexample + +@code{array} needs to be an Objective-C object (usually a collection +object, for example an array, a dictionary or a set) which implements +the ``Fast Enumeration Protocol'' (see below). If you are using a +Foundation library such as GNUstep Base or Apple Cocoa Foundation, all +collection objects in the library implement this protocol and can be +used in this way. + +The code above would iterate over all objects in @code{array}. For +each of them, it assigns it to @code{object}, then executes the +@code{Do something with 'object'} statements. + +Here is a fully worked-out example using a Foundation library (which +provides the implementation of @code{NSArray}, @code{NSString} and +@code{NSLog}): + +@smallexample + NSArray *array = [NSArray arrayWithObjects: @@"1", @@"2", @@"3", nil]; + NSString *object; + + for (object in array) + NSLog (@@"Iterating over %@@", object); +@end smallexample + + +@c ================================ +@node c99 fast enumeration syntax +@subsection c99 fast enumeration syntax + +When compiling with the option @option{-std=c99}, a c99-like +declaration syntax is also allowed: + +@smallexample + id array = @dots{}; + + for (id object in array) + @{ + /* Do something with 'object' */ + @} +@end smallexample + +this is completely equivalent to: + +@smallexample + id array = @dots{}; + + @{ + id object; + for (object in array) + @{ + /* Do something with 'object' */ + @} + @} +@end smallexample + +but can save some typing. + +Note that, unlike other compilers or versions of GCC, this version of +GCC requires the option @option{-std=c99} to allow this syntax in +Objective-C. + +@c ================================ +@node Fast enumeration details +@subsection Fast enumeration details + +Here is a more technical description with the gory details. Consider the code + +@smallexample + for (@var{object expression} in @var{collection expression}) + @{ + @var{statements} + @} +@end smallexample + +here is what happens when you run it: + +@itemize @bullet +@item +@code{@var{collection expression}} is evaluated exactly once and the +result is used as the collection object to iterate over. This means +it is safe to write code such as @code{for (object in [NSDictionary +keyEnumerator]) @dots{}}. + +@item +the iteration is implemented by the compiler by repeatedly getting +batches of objects from the collection object using the fast +enumeration protocol (see below), then iterating over all objects in +the batch. This is faster than a normal enumeration where objects are +retrieved one by one (hence the name ``fast enumeration''). + +@item +if there are no objects in the collection, then +@code{@var{object expression}} is set to @code{nil} and the loop +immediately terminates. + +@item +if there are objects in the collection, then for each object in the +collection (in the order they are returned) @code{@var{object expression}} +is set to the object, then @code{@var{statements}} are executed. + +@item +@code{@var{statements}} can contain @code{break} and @code{continue} +commands, which will abort the iteration or skip to the next loop +iteration as expected. + +@item +when the iteration ends because there are no more objects to iterate +over, @code{@var{object expression}} is set to @code{nil}. This allows +you to determine whether the iteration finished because a @code{break} +command was used (in which case @code{@var{object expression}} will remain +set to the last object that was iterated over) or because it iterated +over all the objects (in which case @code{@var{object expression}} will be +set to @code{nil}). + +@item +@code{@var{statements}} must not make any changes to the collection +object; if they do, it is a hard error and the fast enumeration +terminates by invoking @code{objc_enumerationMutation}, a runtime +function that normally aborts the program but which can be customized +by Foundation libraries via @code{objc_set_mutation_handler} to do +something different, such as raising an exception. + +@end itemize + +@c ================================ +@node Fast enumeration protocol +@subsection Fast enumeration protocol + +If you want your own collection object to be usable with fast +enumeration, you need to have it implement the method + +@smallexample +- (unsigned long) countByEnumeratingWithState: (NSFastEnumerationState *)state + objects: (id *)objects + count: (unsigneld long)len; +@end smallexample + +where @code{NSFastEnumerationState} must be defined in your code as follows: + +@smallexample +typdef struct +@{ + unsigned long state; + id *itemsPtr; + unsigned long *mutationsPtr; + unsigned long extra[5]; +@} NSFastEnumerationState; +@end smallexample + +If no @code{NSFastEnumerationState} is defined in your code, the +compiler will automatically replace @code{NSFastEnumerationState *} +with @code{struct __objcFastEnumerationState *}, where that type is +silently defined by the compiler in an identical way. This can be +confusing and we recommend that you define +@code{NSFastEnumerationState} (as shown above) instead. + +The method is called repeatedly during a fast enumeration to retrieve +batches of objects. Each invocation of the method should retrieve the +next batch of objects. + +The return value of the method is the number of objects in the current +batch; this should not exceed @code{len}, which is the maximum size of +a batch as requested by the caller. The batch itself is returned in +the @code{itemsPtr} field of the @code{NSFastEnumerationState} struct. + +To help with returning the objects, the @code{objects} array is a C +array preallocated by the caller (on the stack) of size @code{len}. +In many cases you can put the objects you want to return in that +@code{objects} array, then do @code{itemsPtr = objects}. But you +don't have to; if your collection already has the objects to return in +some form of C array, it could return them from there instead. + +The @code{state} and @code{extra} fields of the +@code{NSFastEnumerationState} structure allows your collection object +to keep track of the state of the enumeration. In a simple array +implementation, @code{state} may keep track of the index of the last +object that was returned, and @code{extra} may be unused. + +The @code{mutationsPtr} field of the @code{NSFastEnumerationState} is +used to keep track of mutations. It should point to a number; before +working on each object, the fast enumeration loop will check that this +number has not changed. If it has, a mutation has happened and the +fast enumeration will abort. So, @code{mutationsPtr} could be set to +point to some sort of version number of your collection, which is +increased by one every time there is a change (for example when an +object is added or removed). Or, if you are content with less strict +mutation checks, it could point to the number of objects in your +collection or some other value that can be checked to perform an +approximate check that the collection has not been mutated.