| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook MathML Module V1.1b1//EN" |
| "http://www.oasis-open.org/docbook/xml/mathml/1.1CR1/dbmathml.dtd"> |
| |
| |
| <refentry> |
| <refentryinfo> |
| <keywordset> |
| <keyword>Blocks</keyword> |
| </keywordset> |
| </refentryinfo> |
| |
| <refmeta> |
| <refentrytitle>Blocks</refentrytitle> |
| |
| <refmiscinfo> |
| <copyright> |
| <year>2007-2013</year> |
| <holder>The Khronos Group Inc. |
| Permission is hereby granted, free of charge, to any person obtaining a |
| copy of this software and/or associated documentation files (the |
| "Materials"), to deal in the Materials without restriction, including |
| without limitation the rights to use, copy, modify, merge, publish, |
| distribute, sublicense, and/or sell copies of the Materials, and to |
| permit persons to whom the Materials are furnished to do so, subject to |
| the condition that this copyright notice and permission notice shall be included |
| in all copies or substantial portions of the Materials.</holder> |
| </copyright> |
| </refmiscinfo> |
| <manvolnum>3</manvolnum> |
| </refmeta> |
| |
| <!-- ================================ SYNOPSIS --> |
| |
| <refnamediv id="Blocks"> |
| <refname>Blocks</refname> |
| |
| <refpurpose> |
| OpenCL C 2.0 adds support for the clang block syntax. |
| </refpurpose> |
| </refnamediv> |
| |
| <!-- ALTERNATIVE SYNTAX SYNOPSIS (NON-FUNCTION) --> |
| |
| <refsect2 id="synopsis"> |
| <title> |
| </title> |
| |
| <informaltable frame="none"> |
| <tgroup cols="1" align="left" colsep="0" rowsep="0"> |
| <colspec colname="col1" colnum="1" /> |
| <tbody> |
| <row> |
| <entry> |
| Example: |
| int multiplier = 7; |
| int (^myBlock)(int) = ^(int num) { return num * multiplier; }; |
| </entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </informaltable> |
| </refsect2> |
| |
| |
| <!-- ================================ DESCRIPTION --> |
| |
| <refsect1 id="description"><title>Description</title> |
| <para> |
| OpenCL C 2.0 adds support for the clang block syntax. |
| Like function types, the 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 global |
| memory. |
| </para> |
| |
| <para> |
| This syntax is already part of the clang source tree |
| on which most vendors have based their OpenCL |
| implementations. Additionally, blocks based closures |
| are supported by the clang open source C compiler as well as |
| Mac OS X’s C and Objective C compilers. Specifically, |
| Mac OS X’s Grand Central Dispatch allows applications to |
| queue tasks as a block. |
| </para> |
| |
| <bridgehead>Declaring and Using a Block</bridgehead> |
| |
| <para> |
| You use the ^ operator to declare a Block |
| variable and to indicate the beginning of a Block |
| literal. The body of the Block itself is contained |
| within {}, as shown in the example (as usual |
| with C, ; indicates the end of the statement). |
| </para> |
| |
| <!-- the spec has a diagram here --> |
| |
| <para> |
| The Block is able to make use of variables from |
| the same scope in which it was defined. |
| </para> |
| |
| <para> |
| If you declare a Block as a variable, you can |
| then use it just as you would a function: |
| </para> |
| |
| |
| <para> |
| <code><literallayout> |
| int multiplier = 7; |
| int (^myBlock)(int) = ^(int num) { |
| return num * multiplier; |
| }; |
| |
| printf(“%d\n”, myBlock(3)); |
| // prints 21 |
| </literallayout></code> |
| </para> |
| |
| |
| <bridgehead>Declaring a Block Reference</bridgehead> |
| |
| <para> |
| Block variables hold references to Blocks. You |
| declare them using syntax similar to that you use |
| to declare a pointer to a function, except that |
| you use ^ instead of *. The Block type fully |
| interoperates with the rest of the C type system. |
| The following are valid Block variable |
| declarations: |
| </para> |
| |
| <literallayout><code> |
| void (^blockReturningVoidWithVoidArgument)(void); |
| int (^blockReturningIntWithIntAndCharArguments)(int, char); |
| </code></literallayout> |
| |
| <para> |
| A Block that takes no arguments must specify void |
| in the argument list. A Block reference may |
| not be dereferenced via the pointer dereference |
| operation *, and thus a Block’s size may not be |
| computed at compile time. |
| </para> |
| |
| <para> |
| Blocks are designed to be fully type safe by giving |
| the compiler a full set of metadata to use to |
| validate use of Blocks, parameters passed to blocks, |
| and assignment of the return value. |
| </para> |
| |
| <para> |
| You can also create types for Blocks—doing so |
| is generally considered to be best practice when |
| you use a block with a given signature in multiple places: |
| </para> |
| |
| <literallayout><code> |
| typedef float (^MyBlockType)(float, float); |
| |
| MyBlockType myFirstBlock = // …; |
| MyBlockType mySecondBlock = // …; |
| </code></literallayout> |
| |
| <bridgehead>Block Literal Expressions</bridgehead> |
| |
| <para> |
| A Block literal expression produces a reference |
| to a Block. It is introduced by the use of the ^ |
| token as a unary operator. |
| </para> |
| |
| <literallayout><code> |
| Block_literal_expression ::= ^ block_decl compound_statement_body |
| block_decl ::= |
| block_decl ::= parameter_list |
| block_decl ::= type_expression |
| </code></literallayout> |
| |
| <para> |
| where type expression is extended to allow ^ as |
| a Block reference where * is allowed as a |
| function reference. |
| </para> |
| |
| <para> |
| The following Block literal: |
| </para> |
| |
| <literallayout><code> |
| ^ void (void) { printf("hello world\n"); } |
| </code></literallayout> |
| |
| <para> |
| produces a reference to a Block with no arguments with no return value. |
| </para> |
| |
| <para> |
| 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 |
| ( <type>void</type> ), |
| the ( <type>void</type> ) argument list may also be |
| omitted. |
| </para> |
| |
| <para> |
| So: |
| </para> |
| |
| <literallayout><code> |
| ^ ( void ) { printf("hello world\n"); } |
| </code></literallayout> |
| |
| <para> |
| and: |
| </para> |
| |
| <literallayout><code> |
| ^ { printf("hello world\n"); } |
| </code></literallayout> |
| |
| <para> |
| are exactly equivalent constructs for the same expression. |
| </para> |
| |
| <para> |
| 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. |
| </para> |
| |
| <para> |
| 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. |
| </para> |
| |
| <para> |
| The compiler is not required to capture a variable if |
| it can prove that no references to the variable |
| will actually be evaluated. |
| </para> |
| |
| <para> |
| The lifetime of variables declared in a Block is that of a function. |
| </para> |
| |
| <para> |
| Block literal expressions may occur within Block |
| literal expressions (nested) and all variables |
| captured by any nested blocks are implicitly also |
| captured in the scopes of their enclosing |
| Blocks. |
| </para> |
| |
| <para> |
| A Block literal expression may be used as the initialization |
| value for Block variables at global or |
| local static scope. |
| </para> |
| |
| <para> |
| You can also declare a Block as a global literal in program scope. |
| </para> |
| |
| <literallayout><code> |
| int GlobalInt = 0; |
| |
| int (^getGlobalInt)(void) = ^{ return GlobalInt; }; |
| </code></literallayout> |
| |
| <para> |
| <bridgehead>Control Flow</bridgehead> |
| </para> |
| |
| <para> |
| The compound statement of a Block is treated much |
| like a function body with respect to control |
| flow in that continue, break and goto do not escape the Block. |
| </para> |
| |
| <bridgehead>Restrictions</bridgehead> |
| |
| <para> |
| The following Blocks features are currently not supported in OpenCL C. |
| </para> |
| |
| <itemizedlist> |
| <listitem><para>The __block storage type.</para></listitem> |
| <listitem><para>The Block_copy() and Block_release() functions that copy and release Blocks.</para></listitem> |
| <listitem><para>Blocks with variadic arguments.</para></listitem> |
| <listitem><para>Arrays of Blocks.</para></listitem> |
| <listitem><para>Blocks as structures and union members.</para></listitem> |
| </itemizedlist> |
| |
| <para> |
| Block literals are assumed to allocate memory at the point of |
| definition and to be destroyed at the |
| end of the same scope. To support these behaviors, |
| additional restrictions in addition to the |
| above feature restrictions are: |
| </para> |
| |
| <itemizedlist> |
| <listitem> |
| <para> |
| Block variables must be defined and used in a way that |
| allows them to be statically |
| determinable at build or "link to executable" time. In particular: |
| </para> |
| |
| <itemizedlist> |
| <listitem>Block variables assigned in one scope must be |
| used only with the same or any |
| nested scope.</listitem> |
| <listitem>The "extern" storage-class specified cannot be |
| used with program scope block |
| variables.</listitem> |
| <listitem>Block variable declarations must be qualified with |
| const. Therefore all block |
| variables must be initialized at declaration time and |
| may not be reassigned.</listitem> |
| <listitem>A block cannot be the return value of a function.</listitem> |
| </itemizedlist> |
| |
| </listitem> |
| |
| <listitem><para>The unary operators (* and &) cannot be used with a Block.</para></listitem> |
| |
| <listitem><para>Blocks cannot be used as expressions of the ternary selection operator (?:).</para></listitem> |
| |
| <listitem><para>A Block cannot reference another Block.</para></listitem> |
| </itemizedlist> |
| |
| <para> |
| OpenCL C does not allow function pointers (see section 6.9) primarily because it is difficult or |
| expensive to implement generic indirections to executable code in many hardware architectures |
| that OpenCL targets. OpenCL C’s design of Blocks is intended to respect that same condition, |
| yielding the restrictions listed here. As such, Blocks allow a form of dynamically enqueued |
| function scheduling without providing a form of runtime synchronous dynamic dispatch |
| analogous to function pointers. |
| </para> |
| </refsect1> |
| |
| <!-- ================================ NOTES --> |
| |
| <!-- |
| <refsect1 id="notes"><title>Notes</title> |
| <para> |
| </para> |
| </refsect1> |
| --> |
| |
| <!-- ================================ EXAMPLE --> |
| |
| <refsect2 id="example1"> |
| <title> |
| Examples |
| </title> |
| |
| Example 1: |
| <literallayout><code> |
| void foo(int *x, int (^bar)(int, int)) |
| { |
| *x = bar(*x, *x); |
| } |
| |
| kernel |
| void k(global int *x, global int *z) |
| { |
| if (some expression) |
| *x = foo(x, |
| ^int(int x, int y){return x+y+*z;}); // legal |
| else |
| *x = foo(x, |
| ^int(int x, int y){return (x*y)-*z;}); // legal |
| } |
| </code></literallayout> |
| |
| |
| Example 2: |
| <literallayout><code> |
| kernel |
| void k(global int *x, global int *z) |
| { |
| int ^(tmp)(int, int); |
| if (some expression) |
| { |
| tmp = ^int(int x, int y){return x+y+*z;}); // illegal |
| } |
| *x = foo(x, tmp); |
| } |
| </code></literallayout> |
| |
| |
| Example 3: |
| <literallayout><code> |
| int GlobalInt = 0; |
| int (^getGlobalInt)(void) = ^{ return GlobalInt; }; // legal |
| int (^getAnotherGlobalInt)(void); // illegal |
| extern int (^getExternGlobalInt)(void); // illegal |
| |
| void foo() |
| { |
| ... |
| getGlobalInt = ^{ return 0; }; // illegal – cannot assign to |
| // a global block variable |
| ... |
| } |
| </code></literallayout> |
| |
| |
| </refsect2> |
| |
| |
| <!-- ================================ SPECIFICATION --> |
| <!-- Set the "uri" attribute in the <olink /> element to the "named destination" for the PDF page |
| --> |
| <refsect1 id="specification"><title>Specification</title> |
| <para> |
| <imageobject> |
| <imagedata fileref="pdficon_small1.gif" format="gif" /> |
| </imageobject> |
| |
| <olink uri="blocks">OpenCL Specification</olink> |
| </para> |
| </refsect1> |
| |
| <!-- ================================ ALSO SEE --> |
| |
| <!-- |
| <refsect1 id="seealso"><title>Also see</title> |
| <para> |
| </para> |
| </refsect1> |
| --> |
| |
| <!-- ============================== COPYRIGHT --> |
| <!-- Content included from copyright.inc.xsl --> |
| |
| <refsect3 id="Copyright"><title></title> |
| <imageobject> |
| <imagedata fileref="KhronosLogo.jpg" format="jpg" /> |
| </imageobject> |
| <para /> |
| </refsect3> |
| |
| <!-- 19-Oct-2015, C lang 2.0 rev 29 --> |
| </refentry> |
| |