362 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| 
 | |
| .. role:: block-term
 | |
| 
 | |
| =================================
 | |
| Language Specification for Blocks
 | |
| =================================
 | |
| 
 | |
| .. contents::
 | |
|    :local:
 | |
| 
 | |
| Revisions
 | |
| =========
 | |
| 
 | |
| - 2008/2/25 --- created
 | |
| - 2008/7/28 --- revised, ``__block`` syntax
 | |
| - 2008/8/13 --- revised, Block globals
 | |
| - 2008/8/21 --- revised, C++ elaboration
 | |
| - 2008/11/1 --- revised, ``__weak`` support
 | |
| - 2009/1/12 --- revised, explicit return types
 | |
| - 2009/2/10 --- revised, ``__block`` objects need retain
 | |
| 
 | |
| Overview
 | |
| ========
 | |
| 
 | |
| A new derived type is introduced to C and, by extension, Objective-C,
 | |
| C++, and Objective-C++
 | |
| 
 | |
| The Block Type
 | |
| ==============
 | |
| 
 | |
| Like function types, the :block-term:`Block type` is a pair consisting
 | |
| of a result value type and a list of parameter types very similar to a
 | |
| function type. Blocks are intended to be used much like functions with
 | |
| the key distinction being that in addition to executable code they
 | |
| also contain various variable bindings to automatic (stack) or managed
 | |
| (heap) memory.
 | |
| 
 | |
| The abstract declarator,
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|    int (^)(char, float)
 | |
| 
 | |
| describes a reference to a Block that, when invoked, takes two
 | |
| parameters, the first of type char and the second of type float, and
 | |
| returns a value of type int.  The Block referenced is of opaque data
 | |
| that may reside in automatic (stack) memory, global memory, or heap
 | |
| memory.
 | |
| 
 | |
| Block Variable Declarations
 | |
| ===========================
 | |
| 
 | |
| A :block-term:`variable with Block type` is declared using function
 | |
| pointer style notation substituting ``^`` for ``*``. The following are
 | |
| valid Block variable declarations:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     void (^blockReturningVoidWithVoidArgument)(void);
 | |
|     int (^blockReturningIntWithIntAndCharArguments)(int, char);
 | |
|     void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);
 | |
| 
 | |
| Variadic ``...`` arguments are supported. [variadic.c] A Block that
 | |
| takes no arguments must specify void in the argument list [voidarg.c].
 | |
| An empty parameter list does not represent, as K&R provide, an
 | |
| unspecified argument list.  Note: both gcc and clang support K&R style
 | |
| as a convenience.
 | |
| 
 | |
| A Block reference may be cast to a pointer of arbitrary type and vice
 | |
| versa. [cast.c] A Block reference may not be dereferenced via the
 | |
| pointer dereference operator ``*``, and thus a Block's size may not be
 | |
| computed at compile time. [sizeof.c]
 | |
| 
 | |
| Block Literal Expressions
 | |
| =========================
 | |
| 
 | |
| A :block-term:`Block literal expression` produces a reference to a
 | |
| Block. It is introduced by the use of the ``^`` token as a unary
 | |
| operator.
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     Block_literal_expression ::=   ^ block_decl compound_statement_body
 | |
|     block_decl ::=
 | |
|     block_decl ::= parameter_list
 | |
|     block_decl ::= type_expression
 | |
| 
 | |
| where type expression is extended to allow ``^`` as a Block reference
 | |
| (pointer) where ``*`` is allowed as a function reference (pointer).
 | |
| 
 | |
| The following Block literal:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     ^ void (void) { printf("hello world\n"); }
 | |
| 
 | |
| produces a reference to a Block with no arguments with no return value.
 | |
| 
 | |
| The return type is optional and is inferred from the return
 | |
| statements. If the return statements return a value, they all must
 | |
| return a value of the same type. If there is no value returned the
 | |
| inferred type of the Block is void; otherwise it is the type of the
 | |
| return statement value.
 | |
| 
 | |
| If the return type is omitted and the argument list is ``( void )``,
 | |
| the ``( void )`` argument list may also be omitted.
 | |
| 
 | |
| So:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     ^ ( void ) { printf("hello world\n"); }
 | |
| 
 | |
| and:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     ^ { printf("hello world\n"); }
 | |
| 
 | |
| are exactly equivalent constructs for the same expression.
 | |
| 
 | |
| The type_expression extends C expression parsing to accommodate Block
 | |
| reference declarations as it accommodates function pointer
 | |
| declarations.
 | |
| 
 | |
| Given:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     typedef int (*pointerToFunctionThatReturnsIntWithCharArg)(char);
 | |
|     pointerToFunctionThatReturnsIntWithCharArg functionPointer;
 | |
|     ^ pointerToFunctionThatReturnsIntWithCharArg (float x) { return functionPointer; }
 | |
| 
 | |
| and:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     ^ int ((*)(float x))(char) { return functionPointer; }
 | |
| 
 | |
| are equivalent expressions, as is:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     ^(float x) { return functionPointer; }
 | |
| 
 | |
| [returnfunctionptr.c]
 | |
| 
 | |
| The compound statement body establishes a new lexical scope within
 | |
| that of its parent. Variables used within the scope of the compound
 | |
| statement are bound to the Block in the normal manner with the
 | |
| exception of those in automatic (stack) storage. Thus one may access
 | |
| functions and global variables as one would expect, as well as static
 | |
| local variables. [testme]
 | |
| 
 | |
| Local automatic (stack) variables referenced within the compound
 | |
| statement of a Block are imported and captured by the Block as const
 | |
| copies. The capture (binding) is performed at the time of the Block
 | |
| literal expression evaluation.
 | |
| 
 | |
| The compiler is not required to capture a variable if it can prove
 | |
| that no references to the variable will actually be evaluated.
 | |
| Programmers can force a variable to be captured by referencing it in a
 | |
| statement at the beginning of the Block, like so:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|   (void) foo;
 | |
| 
 | |
| This matters when capturing the variable has side-effects, as it can
 | |
| in Objective-C or C++.
 | |
| 
 | |
| The lifetime of variables declared in a Block is that of a function;
 | |
| each activation frame contains a new copy of variables declared within
 | |
| the local scope of the Block. Such variable declarations should be
 | |
| allowed anywhere [testme] rather than only when C99 parsing is
 | |
| requested, including for statements. [testme]
 | |
| 
 | |
| Block literal expressions may occur within Block literal expressions
 | |
| (nest) and all variables captured by any nested blocks are implicitly
 | |
| also captured in the scopes of their enclosing Blocks.
 | |
| 
 | |
| A Block literal expression may be used as the initialization value for
 | |
| Block variables at global or local static scope.
 | |
| 
 | |
| The Invoke Operator
 | |
| ===================
 | |
| 
 | |
| Blocks are :block-term:`invoked` using function call syntax with a
 | |
| list of expression parameters of types corresponding to the
 | |
| declaration and returning a result type also according to the
 | |
| declaration. Given:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     int (^x)(char);
 | |
|     void (^z)(void);
 | |
|     int (^(*y))(char) = &x;
 | |
| 
 | |
| the following are all legal Block invocations:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     x('a');
 | |
|     (*y)('a');
 | |
|     (true ? x : *y)('a')
 | |
| 
 | |
| The Copy and Release Operations
 | |
| ===============================
 | |
| 
 | |
| The compiler and runtime provide :block-term:`copy` and
 | |
| :block-term:`release` operations for Block references that create and,
 | |
| in matched use, release allocated storage for referenced Blocks.
 | |
| 
 | |
| The copy operation ``Block_copy()`` is styled as a function that takes
 | |
| an arbitrary Block reference and returns a Block reference of the same
 | |
| type. The release operation, ``Block_release()``, is styled as a
 | |
| function that takes an arbitrary Block reference and, if dynamically
 | |
| matched to a Block copy operation, allows recovery of the referenced
 | |
| allocated memory.
 | |
| 
 | |
| 
 | |
| The ``__block`` Storage Qualifier
 | |
| =================================
 | |
| 
 | |
| In addition to the new Block type we also introduce a new storage
 | |
| qualifier, :block-term:`__block`, for local variables. [testme: a
 | |
| __block declaration within a block literal] The ``__block`` storage
 | |
| qualifier is mutually exclusive to the existing local storage
 | |
| qualifiers auto, register, and static. [testme] Variables qualified by
 | |
| ``__block`` act as if they were in allocated storage and this storage
 | |
| is automatically recovered after last use of said variable.  An
 | |
| implementation may choose an optimization where the storage is
 | |
| initially automatic and only "moved" to allocated (heap) storage upon
 | |
| a Block_copy of a referencing Block.  Such variables may be mutated as
 | |
| normal variables are.
 | |
| 
 | |
| In the case where a ``__block`` variable is a Block one must assume
 | |
| that the ``__block`` variable resides in allocated storage and as such
 | |
| is assumed to reference a Block that is also in allocated storage
 | |
| (that it is the result of a ``Block_copy`` operation).  Despite this
 | |
| there is no provision to do a ``Block_copy`` or a ``Block_release`` if
 | |
| an implementation provides initial automatic storage for Blocks.  This
 | |
| is due to the inherent race condition of potentially several threads
 | |
| trying to update the shared variable and the need for synchronization
 | |
| around disposing of older values and copying new ones.  Such
 | |
| synchronization is beyond the scope of this language specification.
 | |
| 
 | |
| 
 | |
| Control Flow
 | |
| ============
 | |
| 
 | |
| The compound statement of a Block is treated much like a function body
 | |
| with respect to control flow in that goto, break, and continue do not
 | |
| escape the Block.  Exceptions are treated *normally* in that when
 | |
| thrown they pop stack frames until a catch clause is found.
 | |
| 
 | |
| 
 | |
| Objective-C Extensions
 | |
| ======================
 | |
| 
 | |
| Objective-C extends the definition of a Block reference type to be
 | |
| that also of id.  A variable or expression of Block type may be
 | |
| messaged or used as a parameter wherever an id may be. The converse is
 | |
| also true. Block references may thus appear as properties and are
 | |
| subject to the assign, retain, and copy attribute logic that is
 | |
| reserved for objects.
 | |
| 
 | |
| All Blocks are constructed to be Objective-C objects regardless of
 | |
| whether the Objective-C runtime is operational in the program or
 | |
| not. Blocks using automatic (stack) memory are objects and may be
 | |
| messaged, although they may not be assigned into ``__weak`` locations
 | |
| if garbage collection is enabled.
 | |
| 
 | |
| Within a Block literal expression within a method definition
 | |
| references to instance variables are also imported into the lexical
 | |
| scope of the compound statement. These variables are implicitly
 | |
| qualified as references from self, and so self is imported as a const
 | |
| copy. The net effect is that instance variables can be mutated.
 | |
| 
 | |
| The :block-term:`Block_copy` operator retains all objects held in
 | |
| variables of automatic storage referenced within the Block expression
 | |
| (or form strong references if running under garbage collection).
 | |
| Object variables of ``__block`` storage type are assumed to hold
 | |
| normal pointers with no provision for retain and release messages.
 | |
| 
 | |
| Foundation defines (and supplies) ``-copy`` and ``-release`` methods for
 | |
| Blocks.
 | |
| 
 | |
| In the Objective-C and Objective-C++ languages, we allow the
 | |
| ``__weak`` specifier for ``__block`` variables of object type.  If
 | |
| garbage collection is not enabled, this qualifier causes these
 | |
| variables to be kept without retain messages being sent. This
 | |
| knowingly leads to dangling pointers if the Block (or a copy) outlives
 | |
| the lifetime of this object.
 | |
| 
 | |
| In garbage collected environments, the ``__weak`` variable is set to
 | |
| nil when the object it references is collected, as long as the
 | |
| ``__block`` variable resides in the heap (either by default or via
 | |
| ``Block_copy()``).  The initial Apple implementation does in fact
 | |
| start ``__block`` variables on the stack and migrate them to the heap
 | |
| only as a result of a ``Block_copy()`` operation.
 | |
| 
 | |
| It is a runtime error to attempt to assign a reference to a
 | |
| stack-based Block into any storage marked ``__weak``, including
 | |
| ``__weak`` ``__block`` variables.
 | |
| 
 | |
| 
 | |
| C++ Extensions
 | |
| ==============
 | |
| 
 | |
| Block literal expressions within functions are extended to allow const
 | |
| use of C++ objects, pointers, or references held in automatic storage.
 | |
| 
 | |
| As usual, within the block, references to captured variables become
 | |
| const-qualified, as if they were references to members of a const
 | |
| object.  Note that this does not change the type of a variable of
 | |
| reference type.
 | |
| 
 | |
| For example, given a class Foo:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|       Foo foo;
 | |
|       Foo &fooRef = foo;
 | |
|       Foo *fooPtr = &foo;
 | |
| 
 | |
| A Block that referenced these variables would import the variables as
 | |
| const variations:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|       const Foo block_foo = foo;
 | |
|       Foo &block_fooRef = fooRef;
 | |
|       Foo *const block_fooPtr = fooPtr;
 | |
| 
 | |
| Captured variables are copied into the Block at the instant of
 | |
| evaluating the Block literal expression.  They are also copied when
 | |
| calling ``Block_copy()`` on a Block allocated on the stack.  In both
 | |
| cases, they are copied as if the variable were const-qualified, and
 | |
| it's an error if there's no such constructor.
 | |
| 
 | |
| Captured variables in Blocks on the stack are destroyed when control
 | |
| leaves the compound statement that contains the Block literal
 | |
| expression.  Captured variables in Blocks on the heap are destroyed
 | |
| when the reference count of the Block drops to zero.
 | |
| 
 | |
| Variables declared as residing in ``__block`` storage may be initially
 | |
| allocated in the heap or may first appear on the stack and be copied
 | |
| to the heap as a result of a ``Block_copy()`` operation. When copied
 | |
| from the stack, ``__block`` variables are copied using their normal
 | |
| qualification (i.e. without adding const).  In C++11, ``__block``
 | |
| variables are copied as x-values if that is possible, then as l-values
 | |
| if not; if both fail, it's an error.  The destructor for any initial
 | |
| stack-based version is called at the variable's normal end of scope.
 | |
| 
 | |
| References to ``this``, as well as references to non-static members of
 | |
| any enclosing class, are evaluated by capturing ``this`` just like a
 | |
| normal variable of C pointer type.
 | |
| 
 | |
| Member variables that are Blocks may not be overloaded by the types of
 | |
| their arguments.
 | 
