123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- .. 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.
|