| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "xhtml1-transitional.dtd"> |
| <!-- saved from url=(0013)about:internet --> |
| <?xml-stylesheet type="text/xsl" href="mathml.xsl"?><html xmlns="http://www.w3.org/1999/xhtml" xmlns:pref="http://www.w3.org/2002/Math/preference" xmlns:xlink="http://www.w3.org/1999/xlink" pref:renderer="mathplayer-dl"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
| <style xmlns="" type="text/css"> |
| /* This style sets a margin around the entire page */ |
| html, body { |
| margin: 10px; |
| } |
| |
| p { |
| font: normal 16px verdana, sans-serif; |
| margin: 0; |
| padding-bottom:12px; |
| } |
| |
| h1 { |
| font: bold 25px verdana, sans-serif; |
| margin-top: 0; |
| margin-bottom: 3px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| h2 { |
| font: bold 19px verdana, sans-serif; |
| margin-top: 28px; |
| margin-bottom: 3px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| h3 { |
| font: bold 19px verdana, sans-serif !important; |
| margin-top: 28px; |
| margin-bottom: 3px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| li { |
| font: normal 16px verdana, sans-serif; |
| margin-top: 0; |
| margin-bottom: 18px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| .pdparam { |
| font: italic 16px verdana, sans-serif; |
| } |
| |
| .term { |
| font: italic 16px verdana, sans-serif; |
| font-weight: normal; |
| } |
| |
| .type { |
| font: normal 16px verdana, sans-serif !important; |
| } |
| |
| .parameter { |
| font-style: italic; |
| } |
| |
| a:link, a:visited { |
| color: blue; |
| text-decoration: none; |
| font: normal 16px; |
| } |
| |
| a:hover { |
| background-color: #FFFF99; |
| font: normal 16px; |
| } |
| |
| div.funcsynopsis { |
| text-align: left; |
| background-color: #e6e6e6; |
| font: normal 16px verdana, sans-serif; |
| padding-top: 10px; |
| padding-bottom: 10px; |
| } |
| |
| div.funcsynopsis table { |
| border-collapse: separate; |
| font: normal 16px verdana, sans-serif; |
| } |
| |
| div.funcsynopsis td { |
| background-color: #e6e6e6; |
| border: 0 solid #000; |
| padding: 1px; |
| font: normal 16px verdana, sans-serif; |
| } |
| |
| div.refsect1 { |
| font-family: verdana, sans-serif; |
| font-size: 16px; |
| } |
| |
| code.constant { |
| font: normal 16px courier new, monospace !important; |
| } |
| |
| span.errorname { |
| font: normal 16px verdana, sans-serif !important; |
| } |
| |
| code.function { |
| font: bold 16px verdana, sans-serif !important; |
| } |
| |
| b.fsfunc { |
| font: bold 16px verdana, sans-serif !important; |
| } |
| |
| code.varname { |
| font: italic 16px verdana, sans-serif; |
| } |
| |
| code.replaceable { |
| font: italic 16px courier new, monospace; |
| } |
| |
| code.funcdef { |
| font: normal 16px verdana, sans-serif !important; |
| } |
| |
| .citerefentry { |
| font: normal 16px verdana, sans-serif !important; |
| } |
| |
| .parameter { |
| font-style: italic; |
| } |
| |
| code.fsfunc { |
| font: normal 16px verdana, sans-serif !important; |
| } |
| |
| /* PARAMETER: This style controls spacing between the terms in Parameter section */ |
| dt { |
| margin-top: 15px; |
| } |
| |
| /* TABLES: These styles apply to all tables OTHER than the Synopsis and Example tables */ |
| div.refsect1 table { |
| width: 100%; |
| margin-top: 10px; |
| background-color: #FFF; |
| border-collapse: collapse; |
| border-color: #000; |
| border-width: 1px; |
| font: normal 16px verdana, sans-serif; |
| } |
| |
| div.refsect1 th { |
| border-collapse: collapse; |
| border-color: #000; |
| border-width: 1px; |
| font: bold 16px verdana, sans-serif; |
| } |
| |
| div.refsect1 td { |
| background-color: #FFF; |
| padding: 5px; |
| vertical-align: text-top; |
| border-collapse: collapse; |
| border-color: #000; |
| border-width: 1px; |
| font: normal 16px verdana, sans-serif; |
| } |
| |
| div.refsect1 p{ |
| font: normal 16px verdana, sans-serif; |
| margin-top: 8px; |
| margin-bottom: 8px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| |
| /* EXAMPLE: These styles apply only to the Example section */ |
| div.refsect2 { |
| font: normal 16px courier new, monospace !important; |
| } |
| |
| div.refsect2 table { |
| margin-top: 0; |
| background-color: #e6e6e6; |
| width: 100%; |
| border: 0 solid #000; |
| padding: 2px; |
| font: normal 16px courier new, monospace !important; |
| } |
| |
| div.refsect2 td { |
| background-color: #e6e6e6; |
| font: normal 16px courier new, monospace !important; |
| white-space:pre; |
| } |
| |
| /* COPYRIGHT: This style formats the text of the copyright statement at the bottom of the page */ |
| div.refsect3 { |
| font: normal 11px verdana, sans-serif; |
| margin-top: 50px; |
| margin-bottom: 20px; |
| padding-top: 0; |
| padding-bottom: 0; |
| } |
| |
| </style> |
| <title>Blocks</title> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /> |
| <meta name="keywords" content="Blocks" /> |
| </head> |
| <body> |
| <div class="refentry"> |
| <a id="id-1"></a> |
| <div class="titlepage"></div> |
| <div xmlns="" class="refnamediv"> |
| <a xmlns="http://www.w3.org/1999/xhtml" id="Blocks"></a> |
| <h1>Blocks</h1> |
| <p> |
| OpenCL C 2.0 adds support for the clang block syntax. |
| </p> |
| </div> |
| <div class="refsect2"> |
| <a id="synopsis"></a> |
| <h3> |
| </h3> |
| <div class="informaltable"> |
| <table class="informaltable" border="0"> |
| <colgroup> |
| <col align="left" class="col1" /> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td align="left"> |
| Example: |
| int multiplier = 7; |
| int (^myBlock)(int) = ^(int num) { return num * multiplier; }; |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="refsect1"> |
| <a id="description"></a> |
| <h2>Description</h2> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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. |
| </p> |
| <h4><a id="id-1.5.4"></a>Declaring and Using a Block</h4> |
| <p> |
| 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). |
| </p> |
| <p> |
| The Block is able to make use of variables from |
| the same scope in which it was defined. |
| </p> |
| <p> |
| If you declare a Block as a variable, you can |
| then use it just as you would a function: |
| </p> |
| <p> |
| <code class="code"><div class="literallayout"><p><br /> |
| int multiplier = 7;<br /> |
| int (^myBlock)(int) = ^(int num) {<br /> |
| return num * multiplier;<br /> |
| };<br /> |
| <br /> |
| printf(“%d\n”, myBlock(3));<br /> |
| // prints 21<br /> |
| </p></div></code> |
| </p> |
| <h4><a id="id-1.5.9"></a>Declaring a Block Reference</h4> |
| <p> |
| 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: |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| void (^blockReturningVoidWithVoidArgument)(void);<br /> |
| int (^blockReturningIntWithIntAndCharArguments)(int, char);<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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: |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| typedef float (^MyBlockType)(float, float);<br /> |
| <br /> |
| MyBlockType myFirstBlock = // …;<br /> |
| MyBlockType mySecondBlock = // …;<br /> |
| </code> |
| </p> |
| </div> |
| <h4><a id="id-1.5.16"></a>Block Literal Expressions</h4> |
| <p> |
| A Block literal expression produces a reference |
| to a Block. It is introduced by the use of the ^ |
| token as a unary operator. |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| Block_literal_expression ::= ^ block_decl compound_statement_body<br /> |
| block_decl ::=<br /> |
| block_decl ::= parameter_list<br /> |
| block_decl ::= type_expression<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| where type expression is extended to allow ^ as |
| a Block reference where * is allowed as a |
| function reference. |
| </p> |
| <p> |
| The following Block literal: |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| ^ void (void) { printf("hello world\n"); }<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| produces a reference to a Block with no arguments with no return value. |
| </p> |
| <p> |
| 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 |
| ( <span class="type">void</span> ), |
| the ( <span class="type">void</span> ) argument list may also be |
| omitted. |
| </p> |
| <p> |
| So: |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| ^ ( void ) { printf("hello world\n"); }<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| and: |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| ^ { printf("hello world\n"); }<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| are exactly equivalent constructs for the same expression. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| The compiler is not required to capture a variable if |
| it can prove that no references to the variable |
| will actually be evaluated. |
| </p> |
| <p> |
| The lifetime of variables declared in a Block is that of a function. |
| </p> |
| <p> |
| 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. |
| </p> |
| <p> |
| A Block literal expression may be used as the initialization |
| value for Block variables at global or |
| local static scope. |
| </p> |
| <p> |
| You can also declare a Block as a global literal in program scope. |
| </p> |
| <div class="literallayout"> |
| <p> |
| <code class="code"><br /> |
| int GlobalInt = 0;<br /> |
| <br /> |
| int (^getGlobalInt)(void) = ^{ return GlobalInt; };<br /> |
| </code> |
| </p> |
| </div> |
| <p> |
| </p> |
| <h4><a id="id-1.5.37.1"></a>Control Flow</h4> |
| <p> |
| </p> |
| <p> |
| 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. |
| </p> |
| <h4><a id="id-1.5.39"></a>Restrictions</h4> |
| <p> |
| The following Blocks features are currently not supported in OpenCL C. |
| </p> |
| <div class="itemizedlist"> |
| <ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <p>The __block storage type.</p> |
| </li> |
| <li class="listitem"> |
| <p>The Block_copy() and Block_release() functions that copy and release Blocks.</p> |
| </li> |
| <li class="listitem"> |
| <p>Blocks with variadic arguments.</p> |
| </li> |
| <li class="listitem"> |
| <p>Arrays of Blocks.</p> |
| </li> |
| <li class="listitem"> |
| <p>Blocks as structures and union members.</p> |
| </li> |
| </ul> |
| </div> |
| <p> |
| 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: |
| </p> |
| <div class="itemizedlist"> |
| <ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <p> |
| 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: |
| </p> |
| <div class="itemizedlist"> |
| <ul class="itemizedlist" style="list-style-type: circle; "> |
| <li class="listitem">Block variables assigned in one scope must be |
| used only with the same or any |
| nested scope.</li> |
| <li class="listitem">The "extern" storage-class specified cannot be |
| used with program scope block |
| variables.</li> |
| <li class="listitem">Block variable declarations must be qualified with |
| const. Therefore all block |
| variables must be initialized at declaration time and |
| may not be reassigned.</li> |
| <li class="listitem">A block cannot be the return value of a function.</li> |
| </ul> |
| </div> |
| </li> |
| <li class="listitem"> |
| <p>The unary operators (* and &) cannot be used with a Block.</p> |
| </li> |
| <li class="listitem"> |
| <p>Blocks cannot be used as expressions of the ternary selection operator (?:).</p> |
| </li> |
| <li class="listitem"> |
| <p>A Block cannot reference another Block.</p> |
| </li> |
| </ul> |
| </div> |
| <p> |
| 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. |
| </p> |
| </div> |
| <div class="refsect2"><a id="example1"></a><h3> |
| Examples |
| </h3> |
| |
| Example 1: |
| <div class="literallayout"><p><code class="code"><br /> |
| void foo(int *x, int (^bar)(int, int))<br /> |
| {<br /> |
| *x = bar(*x, *x);<br /> |
| }<br /> |
| <br /> |
| kernel<br /> |
| void k(global int *x, global int *z)<br /> |
| {<br /> |
| if (some expression)<br /> |
| *x = foo(x,<br /> |
| ^int(int x, int y){return x+y+*z;}); // legal<br /> |
| else<br /> |
| *x = foo(x,<br /> |
| ^int(int x, int y){return (x*y)-*z;}); // legal<br /> |
| }<br /> |
| </code></p></div> |
| |
| |
| Example 2: |
| <div class="literallayout"><p><code class="code"><br /> |
| kernel<br /> |
| void k(global int *x, global int *z)<br /> |
| {<br /> |
| int ^(tmp)(int, int);<br /> |
| if (some expression)<br /> |
| {<br /> |
| tmp = ^int(int x, int y){return x+y+*z;}); // illegal<br /> |
| }<br /> |
| *x = foo(x, tmp);<br /> |
| }<br /> |
| </code></p></div> |
| |
| |
| Example 3: |
| <div class="literallayout"><p><code class="code"><br /> |
| int GlobalInt = 0;<br /> |
| int (^getGlobalInt)(void) = ^{ return GlobalInt; }; // legal<br /> |
| int (^getAnotherGlobalInt)(void); // illegal<br /> |
| extern int (^getExternGlobalInt)(void); // illegal<br /> |
| <br /> |
| void foo()<br /> |
| {<br /> |
| ...<br /> |
| getGlobalInt = ^{ return 0; }; // illegal – cannot assign to<br /> |
| // a global block variable<br /> |
| ...<br /> |
| }<br /> |
| </code></p></div></div> |
| <div class="refsect1"> |
| <a id="specification"></a> |
| <h2>Specification</h2> |
| <p> |
| <img src="pdficon_small1.gif" /> |
| |
| <a href="https://www.khronos.org/registry/cl/specs/opencl-2.1-openclc.pdf#page=64" target="OpenCL Spec">OpenCL Specification</a> |
| </p> |
| </div> |
| <div xmlns="" class="refsect3" lang="en" xml:lang="en"><a xmlns="http://www.w3.org/1999/xhtml" id="Copyright"></a><h4 xmlns="http://www.w3.org/1999/xhtml"></h4><img xmlns="http://www.w3.org/1999/xhtml" src="KhronosLogo.jpg" /><p xmlns="http://www.w3.org/1999/xhtml"></p>Copyright © 2007-2015 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. |
| </div> |
| </div> |
| </body> |
| </html> |