<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/late-night-cocoa.html comments</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Sat, 06 Jun 2026 19:44:10 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Diogo Tridapalli - 2013-01-29 20:25:37</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Hi Mike,
&lt;br /&gt;
&lt;br /&gt;The link is broken.
&lt;br /&gt;
&lt;br /&gt;[]'s</description><guid isPermaLink="true">bad3b850cfb30ac882ef1faba519f654</guid><pubDate>Tue, 29 Jan 2013 20:25:37 GMT</pubDate></item><item><title>Jonathan Dann - 2008-09-19 06:36:50</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Hi Mike,
&lt;br /&gt;
&lt;br /&gt;Thanks for those, I appreciate you taking the time to give examples too.  It's far easier to read code than listen to it!
&lt;br /&gt;
&lt;br /&gt;I'm using NSOperation at the moment, but now I have a good starting point to see what mileage I can get from these functions.
&lt;br /&gt;
&lt;br /&gt;Thanks again,
&lt;br /&gt;
&lt;br /&gt;Jonathan</description><guid isPermaLink="true">5684eaff44166ac245c353b135e14444</guid><pubDate>Fri, 19 Sep 2008 06:36:50 GMT</pubDate></item><item><title>mikeash - 2008-09-09 02:13:39</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Jonathan, thanks for your kind words.
&lt;br /&gt;
&lt;br /&gt;I'd suggest that these techniques are probably not too useful for things like string searching. If you can break it up into smallish work units, then I recommend using NSOperation and NSOperationQueue (if you can require 10.5) to run them on all available CPU cores. But of course you know your problem space better than I do, so certainly check out everything and come to your own conclusions.
&lt;br /&gt;
&lt;br /&gt;I will give some quick examples though. Beware that all of the below is written in this comment box and has not been tested.
&lt;br /&gt;
&lt;br /&gt;First, a quick re-implementation of that atomic increment function I used as an example in the podcast. This gives an illustration of the fetch/update/commit loop that I discussed:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;int32_t AtomicIncrementInt32(volatile int32_t *intptr)
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool success;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int32_t old;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int32_t new;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;do {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;old = *intptr; // fetch
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new = old + 1; // update
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success = OSAtomicCompareAndSwap32Barrier(old, new, intptr); // commit
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} while(!success); // if commit failed, do it again
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new; // it can be useful to know what the end result was
&lt;br /&gt;}&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;And now here's an illustration of inserting into a linked list. First we need to define a structure for the list nodes:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;struct ListNode
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;id payload;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct ListNode *next;
&lt;br /&gt;}&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;(The 'payload' member can be replaced with anything, even a whole collection of different members. What it contains is up to you.)
&lt;br /&gt;
&lt;br /&gt;And now, the insert function:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;void AtomicInsertListNodeAtHead(struct ListNode * volatile *head, struct ListNode *newnode)
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool success;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct ListNode oldhead;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;do {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oldhead = *head; // fetch
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newnode-&amp;gt;next = oldhead; // update
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success = OSAtomicCompareAndSwapPtrBarrier(oldhead, newnode, head); // commit
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} while(!success);
&lt;br /&gt;}&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;This follows the same basic pattern. Here, we update the next pointer to point at the old head. Then we do the CAS to replace the head pointer. If it fails, something else updated the list before we could, so start over.
&lt;br /&gt;
&lt;br /&gt;Note, avoid the temptation to write a &lt;code&gt;AtomicRemoveListNodeAtHead&lt;/code&gt; function using this same basic pattern. It may look easy, but you run into that ABA problem I discussed and that is extremely non-trivial to solve.
&lt;br /&gt;
&lt;br /&gt;So, what if you really do want to support removal? Well, that's where that built-in atomic queue stuff comes in. Instead of writing our own list node stuff, we can use Apple's:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;OSQueueHead queue = OS_ATOMIC_QUEUE_INIT;
&lt;br /&gt;
&lt;br /&gt;OSAtomicEnqueue(&amp;amp;queue, newnode, offsetof(struct ListNode, next));
&lt;br /&gt;
&lt;br /&gt;struct ListNode *dequeued = OSAtomicDequeue(&amp;amp;queue, offsetof(struct ListNode, next));&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;And Apple takes care of solving all that ABA nastiness and wrapping it all up in a couple of really simple functions.</description><guid isPermaLink="true">71a923b30ea6a511b4930f8cf68966d9</guid><pubDate>Tue, 09 Sep 2008 02:13:39 GMT</pubDate></item><item><title>Jonathan Dann - 2008-09-06 20:40:57</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Hi Mike,
&lt;br /&gt;
&lt;br /&gt;Really liked the episode, although you said that Apple had done the hard work you still made it comprehensible.
&lt;br /&gt;
&lt;br /&gt;Do you have any example code that would demonstrate some of these operations? I do a lot of string searching in my app and it's be fun to see if I can improve performance with these.
&lt;br /&gt;
&lt;br /&gt;Thanks,
&lt;br /&gt;
&lt;br /&gt;Jonathan</description><guid isPermaLink="true">649a800f2fbe446ff81825bbe4443901</guid><pubDate>Sat, 06 Sep 2008 20:40:57 GMT</pubDate></item><item><title>mikeash - 2008-09-06 10:39:31</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Glad you liked it. I'm not surprised that you found it slow at the beginning. I really wanted to justify the approach and put it into context, and that meant a discussion of more traditional multithreading which is pretty much just a retread for anyone who's already very familiar with it.</description><guid isPermaLink="true">afcedebd5cfb209944cb30e7baaf10a2</guid><pubDate>Sat, 06 Sep 2008 10:39:31 GMT</pubDate></item><item><title>foobaz - 2008-09-06 10:22:45</title><link>http://www.mikeash.com/?page=pyblog/late-night-cocoa.html#comments</link><description>Thanks, this is relevant to my interests. The show started out a little slow but it got interesting about 20:00.</description><guid isPermaLink="true">4ebbfa658f9a1ec403074ec259c277f4</guid><pubDate>Sat, 06 Sep 2008 10:22:45 GMT</pubDate></item></channel></rss>
