<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">David,<div><br></div><div>I'm unfamiliar with the Brad Cox implementation of Blocks (though I know he's been a strong advocate for the feature). A few years ago, Brad and I worked on an ObjC "history" article for <a href="http://en.wikipedia.org/wiki/HOPL">http://en.wikipedia.org/wiki/HOPL</a><a href="http://en.wikipedia.org/wiki/HOPL" style="text-decoration: none;"><font class="Apple-style-span" color="#000000" style=""> (and blocks weren't mentioned). Can you point me to any references? (I'm confused).</font></a></div><div><br></div><div>Thanks,</div><div><br></div><div>snaroff</div><div><br></div><div>On Sep 2, 2008, at 11:27 AM, David Chisnall wrote:</div><div><div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Hi Chris,<br><br>A couple of questions about this:<br><br>1) In Seaside (Smalltalk web-app framework) blocks are used as a way  <br>of implementing continuation passing.  This requires support for re- <br>binding variables in the closure.  Smalltalk does this via the  <br>BlockContext object.  Is there an equivalent of it here?<br><br>2) I know of two existing implementations of blocks in Objective-C,  <br>one by Brad Cox in 1991 and one by David Stes in 1998.  Both used  <br>similar syntax (David Stes simply made untyped arguments default to  <br>id).  What was the rationale for designing a new syntax for block  <br>literals?  Was this to allow Objective-C syntax blocks which are  <br>objects encapsulating C blocks?<br><br>3) Why is the __block storage class required as an explicit type  <br>tag?  Can this not be inferred by the compiler (i.e. any variable you  <br>assign to in the block is promoted, others are copied)?<br><br>3a) It isn't clear from your example what happens if I create a block  <br>referencing a (non-__block) variable, assign it to a global variable  <br>(or an instance variable in another object somewhere), modify the  <br>referenced variable on the stack, and then invoke the block  <br>function.  Does the block see the old or the new value?  If it's the  <br>old value, then I think this answers my previous question but sounds  <br>like it will confuse programmers.  It seems that it would be less  <br>confusing if every block-reference variable implicitly received the  <br>__block storage class, and an explicit tag was made available for  <br>variables which should be bound-by-copy.<br><br>Exciting news, anyway.  I look forward to being able to replace my  <br>Objective-C BlockClosure class used in Smalltalk with something  <br>better supported.  Being able to pass blocks to Objective-C code from  <br>Smalltalk has reduced code complexity in a lot of cases for us, and  <br>being able to do the same thing (and the converse) from Objective-C  <br>is likely to make a lot of people very happy.<br><br>David<br><br>On 28 Aug 2008, at 04:00, Chris Lattner wrote:<br><br><blockquote type="cite">Hi All,<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Steve has started working on an implementation of a language feature<br></blockquote><blockquote type="cite">named 'Blocks'.  The back story on this was that it was prototyped in<br></blockquote><blockquote type="cite">an private Clang fork (because it is much easier to experiment with<br></blockquote><blockquote type="cite">clang than with GCC), then implemented in GCC (where it evolved a<br></blockquote><blockquote type="cite">lot), and now we're re-implementing it in Clang.  The language feature<br></blockquote><blockquote type="cite">is already supported by mainline llvm-gcc, but we don't have up-to-<br></blockquote><blockquote type="cite">date documentation for it.  When that documentation is updated, it<br></blockquote><blockquote type="cite">will definitely be checked into the main clang repo (in clang/docs).<br></blockquote><blockquote type="cite">Note that llvm-gcc supports a bunch of deprecated syntax from the<br></blockquote><blockquote type="cite">evolution of Blocks, but we don't plan to support that old stuff in<br></blockquote><blockquote type="cite">Clang.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Until there is more real documentation, this is a basic idea of<br></blockquote><blockquote type="cite">Blocks: it is closures for C.  It lets you pass around units of<br></blockquote><blockquote type="cite">computation that can be executed later.  For example:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void call_a_block(void (^blockptr)(int)) {<br></blockquote><blockquote type="cite">   blockptr(4);<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void test() {<br></blockquote><blockquote type="cite">   int X = ...<br></blockquote><blockquote type="cite">   call_a_block(^(int y){ print(X+y); });  // references stack var<br></blockquote><blockquote type="cite">snapshot<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">   call_a_block(^(int y){ print(y*y); });<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">In this example, when the first block is formed, it snapshots the<br></blockquote><blockquote type="cite">value of X into the block and builds a small structure on the stack.<br></blockquote><blockquote type="cite">Passing the block pointer down to call_a_block passes a pointer to<br></blockquote><blockquote type="cite">this stack object.  Invoking a block (with function call syntax) loads<br></blockquote><blockquote type="cite">the relevant info out of the struct and calls it.  call_a_block can<br></blockquote><blockquote type="cite">obviously be passed different blocks as long as they have the same  <br></blockquote><blockquote type="cite">type.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> From a technical perspective, blocks fit into C in a couple places:<br></blockquote><blockquote type="cite">1) a new declaration type (the caret) which work very much like a<br></blockquote><blockquote type="cite">magic kind of pointer that can only point to function types. 2) block<br></blockquote><blockquote type="cite">literals, which capture the computation  3) a new storage class<br></blockquote><blockquote type="cite">__block 4) a really tiny runtime library.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">The new storage class comes into play when you want to get mutable<br></blockquote><blockquote type="cite">access to variables on the stack.  Basically you can mark an  <br></blockquote><blockquote type="cite">otherwise-<br></blockquote><blockquote type="cite">auto variable with __block (which is currently a macro that expands to<br></blockquote><blockquote type="cite">an attribute), for example:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void test() {<br></blockquote><blockquote type="cite">   int X = ...<br></blockquote><blockquote type="cite">   __block int Y = ...<br></blockquote><blockquote type="cite">   ^{ X = 4; };  // error, can't modify a const snapshot.<br></blockquote><blockquote type="cite">   ^{ Y = 4; };  // ok!<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> From the implementation standpoint, roughly the address of a __block<br></blockquote><blockquote type="cite">object is captured by the block instead of its value.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">The is tricky though because blocks are on the stack, and you may want<br></blockquote><blockquote type="cite">to refer to some computation (and its __block captured variables)<br></blockquote><blockquote type="cite">after the function returns.  To do this, we have a simple form of<br></blockquote><blockquote type="cite">reference counting to manage the lifetimes of these.  For example, in<br></blockquote><blockquote type="cite">this case:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void (^P)(int);  // global var<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void gets_a_block(void (^blockptr)(int)) {<br></blockquote><blockquote type="cite">   P = blockptr;<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void called_sometime_later() {<br></blockquote><blockquote type="cite">   P(4);<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">if gets_a_block is called with a block on the stack, and<br></blockquote><blockquote type="cite">called_sometime_later is called after that stack frame is popped,<br></blockquote><blockquote type="cite">badness happens (yay for C!).  Instead, we use:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void (^P)(int);  // global var<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void gets_a_block(void (^blockptr)(int)) {<br></blockquote><blockquote type="cite">   P = _Block_copy(blockptr);  // copies to heap if on the stack with<br></blockquote><blockquote type="cite">refcount +1, otherwise increments refcount.<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">void called_sometime_later() {<br></blockquote><blockquote type="cite">   P(4);<br></blockquote><blockquote type="cite">   _Block_release(P);  // decrements refcount.<br></blockquote><blockquote type="cite">   P = 0;<br></blockquote><blockquote type="cite">}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">The semantics of this is that it copies the block off the stack *as<br></blockquote><blockquote type="cite">well as any __block variables it references*, and the shared __block<br></blockquote><blockquote type="cite">variables are themselves freed when all referencing blocks go away.<br></blockquote><blockquote type="cite">The really tiny runtime library implements things like _Block_copy and<br></blockquote><blockquote type="cite">friends.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Other interesting things are that the blocks themselves do limited/<br></blockquote><blockquote type="cite">optional type inference of the result type:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">   foo(^int(){ return 4; });   // takes nothing, returns int.<br></blockquote><blockquote type="cite">   foo(^(){ return 4; });      // same thing, inferred to return int.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">If you're interested in some more low-level details, it looks like  <br></blockquote><blockquote type="cite">gcc/<br></blockquote><blockquote type="cite">testsuite/gcc.apple/block-blocks-test-8.c in the llvm-gcc testsuite<br></blockquote><blockquote type="cite">has some of the underlying layout info, though I have no idea if it is<br></blockquote><blockquote type="cite">up-to-date.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">To head off the obvious question: this syntax and implementation has<br></blockquote><blockquote type="cite">nothing to do with C++ lambdas.  Blocks are designed to work well with<br></blockquote><blockquote type="cite">C and Objective-C, and unfortunately C++ lambdas really require a<br></blockquote><blockquote type="cite">language with templates to be very useful.  The syntax of blocks  <br></blockquote><blockquote type="cite">and C+<br></blockquote><blockquote type="cite">+ lambdas are completely different, so we expect to eventually support<br></blockquote><blockquote type="cite">both in the same compiler.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">In any case, more detailed documentation will be forthcoming, but I<br></blockquote><blockquote type="cite">would be happy to answer specific questions (before Friday, at which<br></blockquote><blockquote type="cite">point I disappear for two weeks on vacation, woo!)<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">-Chris<br></blockquote><blockquote type="cite">_______________________________________________<br></blockquote><blockquote type="cite">cfe-dev mailing list<br></blockquote><blockquote type="cite"><a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br></blockquote><blockquote type="cite"><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br></blockquote><br>_______________________________________________<br>cfe-dev mailing list<br><a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev<br></div></blockquote></div><br></div></body></html>