<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tao Effect Blog &#187; Free Stuff</title>
	<atom:link href="http://www.taoeffect.com/blog/category/free-stuff/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.taoeffect.com/blog</link>
	<description>Notice the Tao Effects...</description>
	<lastBuildDate>Fri, 03 Feb 2012 17:58:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>DelayedLauncher 2.2</title>
		<link>http://www.taoeffect.com/blog/2011/01/delayedlauncher-2-2/</link>
		<comments>http://www.taoeffect.com/blog/2011/01/delayedlauncher-2-2/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 23:45:20 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[delayedlauncher]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=2485</guid>
		<description><![CDATA[DelayedLauncher gets an icon thanks to Lorenzo Orlandi! NEW: New icon by @lorenzorlandi &#8212; thanks!! NEW: Reveal In Finder contextual menu item Requirements: Mac OS X 10.4+]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2011/01/DelayedLauncher-e1295998988169.png" alt="" title="DelayedLauncher" width="400" height="286" class="alignnone size-full wp-image-2491" /></center></p>
<p><a href="/blog/2010/03/delayedlauncher-2-0/">DelayedLauncher</a> gets an icon thanks to <a href="http://twitter.com/lorenzorlandi">Lorenzo Orlandi</a>! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<ul class="box">
<li><b>NEW:</b> New icon by @lorenzorlandi &#8212; thanks!!</li>
<li><b>NEW:</b> Reveal In Finder contextual menu item</li>
</ul>
<p><a href="/delayedlauncher/DelayedLauncher.zip" style="border:none"><img src="http://www.taoeffect.com/blog/wp-content/uploads/2008/12/delayedlauncherzip.png" alt="" title="DelayedLauncher" /></a><br />
Requirements: Mac OS X 10.4+</p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2011/01/delayedlauncher-2-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DelayedLauncher 2.0</title>
		<link>http://www.taoeffect.com/blog/2010/03/delayedlauncher-2-0/</link>
		<comments>http://www.taoeffect.com/blog/2010/03/delayedlauncher-2-0/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 20:55:47 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[delayedlauncher]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=1932</guid>
		<description><![CDATA[And you thought I&#8217;d abandoned it. DelayedLauncher turned out to be more popular than I expected it to be. Originally released as a solution to a problem in the 1.x series of Espionage, DelayedLauncher turned out to be useful for many people as a way of speeding up their system&#8217;s login time. After receiving enough [...]]]></description>
			<content:encoded><![CDATA[<p><center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2010/03/DelayedLauncher_cropped.png" alt="DelayedLauncher 2.0" title="Delayed Launcher 2.0" class="alignnone size-full wp-image-1933" /></center></p>
<p>And you thought I&#8217;d abandoned it. <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p><b>DelayedLauncher</b> turned out to be more popular than I expected it to be.</p>
<p>Originally released as <a href="/blog/2008/12/delayedlauncher-coming-to-an-espionage-near-you/">a solution to a problem in the 1.x series of Espionage</a>, DelayedLauncher turned out to be useful for many people as a way of speeding up their system&#8217;s login time.</p>
<p>After receiving enough emails asking for the ability to specify delays for each of the items, it is finally here, DelayedLauncher 2.0, and yes, it&#8217;s still completely free. <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><a href="http://www.taoeffect.com/delayedlauncher/DelayedLauncher.zip" style="border:none"><img src="http://www.taoeffect.com/blog/wp-content/uploads/2008/12/delayedlauncherzip.png" alt="" title="DelayedLauncher" /></a><br />
Requirements: Mac OS X 10.4+</p>
<p><i><strike>P.S. If you&#8217;d like to contribute an icon for it, just <a href="/about/">contact us</a>. I think a rocket with a wrist-watch strapped around it would suit it nicely.</strike></i></p>
<p><b>Update: <a href="/blog/2011/01/delayedlauncher-2-2/">Version 2.2 fixes bugs and has a new icon!</a></b></p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2010/03/delayedlauncher-2-0/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Easy Cocoa Setup Assistants with TESetupAssistant</title>
		<link>http://www.taoeffect.com/blog/2010/01/easy-cocoa-setup-assistants-with-tesetupassistant/</link>
		<comments>http://www.taoeffect.com/blog/2010/01/easy-cocoa-setup-assistants-with-tesetupassistant/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 02:25:59 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=1766</guid>
		<description><![CDATA[Setup assistants can be a great tool when you need to guide users through a series of steps. TESetupAssistant was born during my work on the 2.0 update to Espionage, when I discovered that many of its UI elements could stand to benefit from a generic setup assistant class. The gallery below shows some of [...]]]></description>
			<content:encoded><![CDATA[<p>Setup assistants can be a great tool when you need to guide users through a series of steps.</p>
<p><b>TESetupAssistant</b> was born during my work on the <a href="/blog/2009/02/espionage-20-released/">2.0 update</a> to <a href="/espionage">Espionage</a>, when I discovered that many of its UI elements could stand to benefit from a generic setup assistant class.</p>
<p>The gallery below shows some of the places in Espionage where we use TESetupAssisant, illustrating its versatility:</p>
<div class="imageGallery" style="background-color:black">
<ul style="width:500px">
<li><a rel="imageGallery" href="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/keychain.png" title="Switching keychains"><img style="margin-top:20px" src="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/keychain_thumb.png"/></a></li>
<li><a rel="imageGallery" title="Encrypting application data" href="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/apptemplates.png"><img src="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/apptemplates_thumb.png" /></a></li>
<li class="right"><a rel="imageGallery" title="Installing Espionage itself" href="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/install.png"><img style="margin-top:25px" src="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/install_thumb.png" /></a></li>
</ul>
<div class="clear"></div>
</div>
<p>You can create these sorts of UIs very quickly and use them wherever the user needs to complete a series of steps, or even a single step (as shown in the first image above). Here&#8217;s a basic overview of it:</p>
<p><center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/TESetupAssistant.png" /></center></p>
<p>There are two main classes: <B>TESetupAssistant</b> and <B>TEBaseAssistant</b>. TESetupAssistant is associated with a nib file that determines the overall layout. It manages a one or more assistants, each of which inherit from TEBaseAssistant. Each TEBaseAssistant subclass has its own nib file, usually just containing a single NSView container object.</p>
<h3>Example of a Modal Assistant</h3>
<p>Here&#8217;s an example of a very simple assistant using the minified UI and running modally:</p>
<p><center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2010/01/simple_assistant.png"/></center></p>
<p>And here is all the code needed to create it:</p>
<pre class="code">
<span class="source source_objc"><span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_other string_quoted_other_lt-gt string_quoted_other_lt-gt_include string_quoted_other_lt-gt_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">&lt;</span>Cocoa/Cocoa.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">&gt;</span></span></span>
<span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_double string_quoted_double_include string_quoted_double_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>TESetupAssistant.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span></span>

<span class="meta meta_interface-or-protocol meta_interface-or-protocol_objc"><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>interface</span> <span class="entity entity_name entity_name_type entity_name_type_objc">MiniAssistant</span> <span class="punctuation punctuation_definition punctuation_definition_entity punctuation_definition_entity_other punctuation_definition_entity_other_inherited-class punctuation_definition_entity_other_inherited-class_objc">:</span> <span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_objc">TEBaseAssistant</span><span class="meta meta_divider meta_divider_objc"> </span><span class="meta meta_scope meta_scope_interface meta_scope_interface_objc">{
    <span class="storage storage_type storage_type_objc">IBOutlet</span> <span class="support support_class support_class_cocoa">NSTextField</span> *textField;
}
</span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>end</span></span>

<span class="meta meta_implementation meta_implementation_objc"><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>implementation</span> <span class="entity entity_name entity_name_type entity_name_type_objc">MiniAssistant</span>
<span class="meta meta_scope meta_scope_implementation meta_scope_implementation_objc"><span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="support support_class support_class_cocoa">NSArray</span> *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">orderedSteps</span></span>
</span>{
    <span class="keyword keyword_control keyword_control_c">return</span> <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSArray</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">arrayWithObject<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Mini Step<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">start</span></span>
</span>{
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>controller <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">nextButton</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setTitle<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Finish<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>textField <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setStringValue<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>NSSTR_FMT(
        <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Hi there! I'm a mini-assistant <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%s</span>running modally!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>,
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>controller <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">modal</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> ? <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span> : <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>not <span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>)
    </span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}
</span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>end</span></span>

<span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> To run it modally is just 4 lines of code (somewhere):
</span>
TESetupAssistant *sa = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESetupAssistant <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">alloc</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">initMini</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">autorelease</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>sa <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setModal<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">YES</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>sa <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">addAssistant<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>MiniAssistant <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">assistant</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>sa <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">run</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;</span>
</pre>
<p>Notice that we don&#8217;t even need to load the nib file. That&#8217;s because our nib file is named after our assitant (MiniAssistant.nib). You can of course override the <span class="code">-assistantNib</span> method to specify a different one, but that illustrates one key aspect of TESetupAssistant, and that is that there are sensible defaults for almost everything, allowing you to quickly throw together these kinds of interfaces.</p>
<h3>Get It On Github</h3>
<p>I&#8217;m releasing TESetupAssistant as open source under a liberal license (just an attribution is asked for), and I&#8217;ve included a little demo app to help you hit the ground running. You can <a href="https://github.com/taoeffect/TESetupAssistant/zipball/master">download</a> it <a href="http://github.com/taoeffect/TESetupAssistant">on github</a>.</p>
<p>If you use it in your application I&#8217;d love to know! Shoot us an email or post a comment below and I&#8217;ll place a link here to your app.</p>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><i style="color:inherit">You can follow me on twitter <a href="http://twitter.com/taoeffect">here</a>.</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2010/01/easy-cocoa-setup-assistants-with-tesetupassistant/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introducing Objective newLISP</title>
		<link>http://www.taoeffect.com/blog/2009/12/introducing-objective-newlisp/</link>
		<comments>http://www.taoeffect.com/blog/2009/12/introducing-objective-newlisp/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 08:09:17 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[newLISP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[ObjNL]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=1318</guid>
		<description><![CDATA[newLISP is an awesome language that I use for all of my scripting needs, but one thing that is missing from it is a nice way of doing real object oriented programming. By default it supports a pseudo-OOP paradigm called FOOP, but FOOP is simply inadequate for doing some of the most rudimentary of OOP [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.newlisp.org">newLISP</a> is an awesome language that I use for all of my scripting needs, but one thing that is missing from it is a nice way of doing real object oriented programming.</p>
<p>By default it supports a pseudo-OOP paradigm called <a href="http://www.newlisp.org/downloads/newlisp_manual.html#foop">FOOP</a>, but FOOP is simply inadequate for doing some of the most rudimentary of OOP tasks, such as allowing objects to hold references to each other.</p>
<p>That is why I&#8217;m announcing <b>Objective newLISP: Real Object Oriented Programming for newLISP</b>.</p>
<h3>Let&#8217;s Dive In</h3>
<p>Objective newLISP&mdash;ObjNL for short&mdash;is modeled after parts of Objective-C and Java. Let&#8217;s open up a REPL and begin:</p>
<pre class="code terminal">$ newlisp ObjNL.lsp
newLISP v.10.1.6 on OSX IPv4 UTF-8, execute 'newlisp -h' for more info.
<b></b>
&gt; </pre>
<h4>Classes</h4>
<p>Classes are simply contexts and are defined using the function <span class="code">new-class</span>:</p>
<pre class="code terminal">&gt; (new-class 'Foo)
Foo</pre>
<p>If we wanted to create a subclass of <span class="code">Foo</span> called <span class="code">Bar</span> we can easily do so:</p>
<pre class="code terminal">&gt; (new-class 'Bar Foo)
Bar</pre>
<p>We can see that <span class="code">Foo</span> is the superclass of <span class="code">Bar</span>:</p>
<pre class="code terminal">&gt; Bar:@super
Foo</pre>
<p>And that all classes inherit from <span class="code">ObjNL</span>:</p>
<pre class="code terminal">&gt; Foo:@super
ObjNL</pre>
<h4>Objects</h4>
<p>Objects are instantiated from classes using the function <span class="code">instantiate</span>. They are contexts too:</p>
<pre class="code terminal">&gt; (setf obj (instantiate Foo))
Foo#1</pre>
<p>As we&#8217;re subverting newLISP&#8217;s <a href="http://www.newlisp.org/MemoryManagement.html">ORO memory management model</a> to gain real OOP, we should deallocate it manually when we&#8217;re through using it. I will cover the topic of <b>memory management</b> last.</p>
<h4>Constructors</h4>
<p>Constructors are defined using the <a href="http://www.newlisp.org/downloads/newlisp_manual.html#default_function">default function</a>. Let&#8217;s define constructors for <span class="code">Foo</span> and <span class="code">Bar</span> (suppose we entered this into the REPL between a pair of <span class="code">[cmd][/cmd]</span> tags):</p>
<pre class="code"><span class="source source_newlisp"><span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">context</span> <span class="entity entity_symbol entity_symbol_lisp">Foo</span><span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="meta meta_function meta_function_lisp"><span class="storage storage_type storage_type_function-type storage_type_function-type_lisp">define</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_functiondef entity_name_functiondef_lisp">Foo:Foo</span></span> <span class="entity entity_symbol entity_symbol_lisp">_bar</span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">bar</span> <span class="entity entity_symbol entity_symbol_lisp">_bar</span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="constant constant_language constant_language_lisp">true</span>
<span class="entity entity_paren entity_paren_lisp">)</span>

<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">context</span> <span class="entity entity_symbol entity_symbol_lisp">Bar</span><span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="meta meta_function meta_function_lisp"><span class="storage storage_type storage_type_function-type storage_type_function-type_lisp">define</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_functiondef entity_name_functiondef_lisp">Bar:Bar</span></span> <span class="entity entity_symbol entity_symbol_lisp">_foo</span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">foo</span> <span class="entity entity_symbol entity_symbol_lisp">_foo</span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="constant constant_language constant_language_lisp">true</span> <span class="comment comment_line comment_line_semicolon comment_line_semicolon_lisp"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_lisp">;</span> don't allow ourselves to be deallocated
</span><span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">context</span> <span class="entity entity_symbol entity_symbol_lisp">MAIN</span><span class="entity entity_paren entity_paren_lisp">)</span></span></pre>
<p>Note the extra <span class="code">true</span> at the end of each constructor. This is important because if the constructor returns <span class="code">nil</span> that tells ObjNL that an error occurred and to therefore deallocate the object immediately. Thus if <span class="code">_bar</span> were <span class="code">nil</span> and we didn&#8217;t have that <span class="code">true</span> the object would be deallocated, and we don&#8217;t want that.</p>
<p>When we call <span class="code">instantiate</span> with extra arguments they are passed to the constructor:</p>
<pre class="code terminal">&gt; (setf obj (instantiate Foo (instantiate Bar)))
Foo#2</pre>
<p>We can see that the instance variables were properly set:</p>
<pre class="code terminal">&gt; obj:bar
Bar#1
> obj:bar:foo

ERR: symbol expected : "obj:bar:foo"</pre>
<p>Huh. We were able to check <span class="code">obj:bar</span> but <span class="code">obj:bar:foo</span> resulted in an error. It seems newLISP treats the entire thing as a symbol if there&#8217;s more than one colon, instead of assuming we&#8217;re doing multiple context lookups.</p>
<p>Thankfully Objective newLISP has you covered.</p>
<h4>Deep Value and Symbol Access</h4>
<pre class="code terminal">&gt; (. obj bar foo)
nil</pre>
<p>The <b>dot macro</b> lets us look up the value of a symbol that we want through several object references. I&#8217;ll refer to this as &#8220;deep value access&#8221;. Sometime we want the <i>symbol</i> instead of the value, for example say for fun we want to create a circular reference between the objects <span class="code">obj</span> and <span class="code">obj:bar</span>. We can do this using the <b>dot-reference macro</b>:</p>
<pre class="code terminal">&gt; (.&#038; obj bar foo)
Bar#1:foo
&gt; (set (.&#038; obj bar foo) obj)
Foo#2</pre>
<p>The dot-reference macro allows for &#8220;deep symbol access&#8221;, it returns the context-qualified symbol for an object&#8217;s instance variable. Now we can show that our circular reference works:</p>
<pre class="code terminal">&gt; (. obj bar foo bar foo)
Foo#2
&gt; (= obj (. obj bar foo bar foo))
true</pre>
<h4>Interfaces</h4>
<p>Most object oriented systems have the concept of an <b>interface</b>, sometimes referred to as a <b>protocol</b>. Interfaces define a set of functions that a class can choose to implement or &#8220;conform&#8221; to. Objective newLISP has them too, and refers to them as interfaces even though they are technically <a href="http://en.wikipedia.org/wiki/Mixin">mixins</a>.</p>
<p>Let&#8217;s define a simple interface called <span class="code">protocol</span>:</p>
<pre class="code terminal">&gt; (define (protocol:test) "hello!")
(lambda () "hello!")</pre>
<p>There are two ways to implement an interface. You can specify a list of them when creating a new class:</p>
<pre class="code terminal">&gt; (new-class 'Foo ObjNL '(protocol))
Foo</pre>
<p>Or you can add them to a class or object after its definition. We actually want to do this right now because we instantiated <span class="code">obj</span> prior to adding <span class="code">protocol</span> to <span class="code">Foo</span>&#8216;s list of interfaces. We can check to see this is true by asking if <span class="code">obj</span> implements <span class="code">protocol</span>:</p>
<pre class="code terminal">&gt; (implements? protocol obj)
nil</pre>
<p>So the second way to add an interface to an object or class is to use the function <span class="code">add-interface</span>:</p>
<pre class="code terminal">&gt; (add-interface protocol obj)
(protocol Foo ObjNL)</pre>
<p>Now <span class="code">obj</span> should implement it, so we can try it out:</p>
<pre class="code terminal">&gt; (if (implements? protocol obj) (obj:test))
"hello!"</pre>
<p>The only real difference between an interface and a class is that a class has a constructor (default function) and ultimately inherits from <span class="code">ObjNL</span>. You can use <span class="code">implements?</span> to check inheritance as well:</p>
<pre class="code terminal">&gt; (implements? ObjNL obj)
true</pre>
<h4>Memory Management</h4>
<p>The last, and perhaps most important topic, is what to do with all those objects you&#8217;ve got lying around, also referred to as &#8220;memory management.&#8221;</p>
<p>Objective newLISP supports two styles of memory management: manual and reference counting.</p>
<p><b>Manual memory management</b> is simple: <span class="code">instantiate</span> your object, and when you&#8217;re done with it, <span class="code">deallocate</span> it!</p>
<pre class="code terminal">&gt; (setf b (instantiate Bar))
Bar#2
&gt; (deallocate b)
true</pre>
<p><b>Reference counting</b> is done the same way it is done in <a href="http://en.wikipedia.org/wiki/Objective-C">Objective-C</a>.  Each object starts with a <b>reference count</b> of <span class="code">1</span>. When you want to hold onto that object you <span class="code">retain</span> it, and when you&#8217;re through with it you <span class="code">release</span> or <span class="code">autorelease</span> it (which decrements the reference count). When the reference count hits zero the object is deallocated by <span class="code">deallocate</span>:</p>
<pre class="code terminal">&gt; (setf b (instantiate Bar))
Bar#3
&gt; (release b)
true</pre>
<p>I will cover <span class="code">autorelease</span> next, but I won&#8217;t go to great lengths to explain how all of this reference counting stuff works. If you&#8217;re unfamiliar with it, just know that it&#8217;s not complicated. If you want some practice make an iPhone app. <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>To illustrate <span class="code">autorelease</span>  I will implement the method <span class="code">ObjNL:dealloc</span>, which is called on an object just before it is deallocated.</p>
<pre class="code terminal">&gt; (define (Bar:dealloc) (println Bar:@self " has been deallocated!"))
(lambda () (println "Object " Bar:@self " has been deallocated!"))
&gt; (push-autorelease-pool)
(())
&gt; (dotimes (_ 5) (autorelease (instantiate Bar)))
Bar#8
&gt; (pop-autorelease-pool)
Bar#8 has been deallocated!
Bar#7 has been deallocated!
Bar#6 has been deallocated!
Bar#5 has been deallocated!
Bar#4 has been deallocated!
true</pre>
<p>One important point to mention is that deallocating objects in newLISP versions 10.1.8 or older is <b>very slow</b>. The details of why this is has to do with safety (which I discuss in the box below), but needless to say it was too slow to be acceptable. I contacted Lutz Mueller, the author of newLISP, and he agreed to introduce an &#8220;unsafe&#8221; optimization into the <span class="code">delete</span> function. In versions 10.1.9 and later, deallocating Objective newLISP objects is approximately <b>480 times faster</b>.</p>
<p>Because of this, it&#8217;s strongly recommended to use Objective newLISP with <b>newLISP 10.1.9 or later</b>. Currently the latest development release is 10.1.8, however Lutz graciously made this optimization available online in a development version of 10.1.9. Click <a href="http://www.newlisp.org/downloads/development/latest/newlisp-10.1.9-dev.tgz">here to grab the source</a> for this version. This link will expire soon, when it does you can get the latest development release <a href="http://www.newlisp.org/downloads/development/">here</a>.</p>
<div class="box" style="margin-bottom:20px">
<h4>Cautionary Note!</h4>
<p style="margin-bottom:5px">There are two situations to watch out for when using Objective newLISP:</p>
<p style="margin-bottom:5px"><b>#1: Unbound References in Functions</b></p>
<p style="margin-bottom:5px">Instead of this:</p>
<pre class="code"><span class="source source_newlisp"><span class="entity entity_paren entity_paren_lisp">(</span><span class="meta meta_function meta_function_lisp"><span class="storage storage_type storage_type_function-type storage_type_function-type_lisp">define</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_functiondef entity_name_functiondef_lisp">modify-obj</span></span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">obj:bar</span> <span class="constant constant_numeric constant_numeric_lisp">5</span><span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">obj</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">instantiate</span> <span class="entity entity_symbol entity_symbol_lisp">Foo</span><span class="entity entity_paren entity_paren_lisp">))</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">modify-obj</span><span class="entity entity_paren entity_paren_lisp">)</span></span></pre>
<p style="margin-bottom:5px">Do this:</p>
<pre class="code"><span class="source source_newlisp"><span class="entity entity_paren entity_paren_lisp">(</span><span class="meta meta_function meta_function_lisp"><span class="storage storage_type storage_type_function-type storage_type_function-type_lisp">define</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_functiondef entity_name_functiondef_lisp">modify-obj</span></span> <span class="entity entity_symbol entity_symbol_lisp">obj</span><span class="entity entity_paren entity_paren_lisp">)</span>
    <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">obj:bar</span> <span class="constant constant_numeric constant_numeric_lisp">5</span><span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">)</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">setf</span> <span class="entity entity_symbol entity_symbol_lisp">obj</span> <span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">instantiate</span> <span class="entity entity_symbol entity_symbol_lisp">Foo</span><span class="entity entity_paren entity_paren_lisp">))</span>
<span class="entity entity_paren entity_paren_lisp">(</span><span class="entity entity_name entity_name_function entity_name_function_lisp">modify-obj</span> <span class="entity entity_symbol entity_symbol_lisp">obj</span><span class="entity entity_paren entity_paren_lisp">)</span></span></pre>
<p>If you don&#8217;t do that, newLISP will read the <span class="code">obj:bar</span> in the definition of <span class="code">modify-obj</span> and instantly create and protect a context called <span class="code">obj</span>, making it impossible to <span class="code">setf</span> the <span class="code">obj</span> later on.</p>
<p style="margin-bottom:5px"><b>#2: Dangling References</b></p>
<p style="margin-bottom:5px">Use extreme caution when holding reference(s) to an object in a list or some other container! If that reference is later deallocated and you try to access it, bad things will happen:</p>
<pre class="code terminal">&gt; (setf b (instantiate Bar))
Bar#9
&gt; (push b alist)
Bar#9
&gt; (deallocate b)
Bar#9 has been deallocated!
true
&gt; alist
Bus error</pre>
<p style="margin-bottom:5px">Normally this would not be a problem, the object in <span class="code">alist</span> would simply be replaced with <span class="code">nil</span> upon its deallocation. However, since we&#8217;re using the fast, unsafe version of <span class="code">delete</span> to do our deallocation, newLISP will not do that. It is the same situation as when attempting to access free&#8217;d memory in C/C++/Objective-C.</p>
<p style="margin-bottom:5px">Instead we should use <span class="code">retain</span>/<span class="code">release</span>:</p>
<p class="last">
<pre class="code terminal">&gt; (setf b (instantiate Bar))
Bar#9
&gt; (push (retain b) alist)
Bar#9
&gt; (release b)
nil
&gt; alist
(Bar#9)
&gt; (release (pop alist))
Bar#9 has been deallocated!
true
&gt; alist
()</pre>
</p>
</div>
<h4>When to use FOOP</h4>
<p>Objective newLISP is not the answer to all OOP problems in newLISP. <a href="http://www.newlisp.org/downloads/newlisp_manual.html#foop">FOOP</a> has its place too. If you&#8217;re dealing with a situation where you may end up needing lots of objects, FOOP is probably the better choice. Although you can&#8217;t do full-blown OOP with it, FOOP objects can use far less memory than ObjNL objects because in ObjNL, methods are stored in each object, not in the class. After trying out both you should have a good feeling for when to use one over the other (i.e., if the limitations of FOOP start to become obvious).</p>
<h4>Download and API</h4>
<p><a href="http://github.com/taoeffect/objective-newlisp">You can grab Objective newLISP from Github.</a></p>
<p>Access the <a href="/newlisp/ObjNL.lsp.html">Objective newLISP API</a>.</p>
<p>And for news, follow <a href="http://twitter.com/taoeffect">@taoeffect</a> and <a href="http://twitter.com/newlisp">@newlisp</a> on twitter.</p>
<p>Thanks for checking out Objective newLISP!</p>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/12/introducing-objective-newlisp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a better lock: TESharedObject</title>
		<link>http://www.taoeffect.com/blog/2009/08/building-a-better-lock-tesharedobject/</link>
		<comments>http://www.taoeffect.com/blog/2009/08/building-a-better-lock-tesharedobject/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 01:36:57 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[locks]]></category>
		<category><![CDATA[TESharedObject]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=835</guid>
		<description><![CDATA[While I&#8217;m happy to see Grand Central in Snow Leopard, I won&#8217;t be using it in any of our applications anytime soon because that means we&#8217;d have to turn our backs on all those PPC users out there, and everyone who has yet to upgrade to Snow Leopard. I suspect that this represents a sizable [...]]]></description>
			<content:encoded><![CDATA[<p>While I&#8217;m happy to see Grand Central in Snow Leopard, I won&#8217;t be using it in any of our applications anytime soon because that means we&#8217;d have to turn our backs on all those PPC users out there, and everyone who has yet to upgrade to Snow Leopard. I suspect that this represents a sizable chunk of the OS X using population, at least at the moment.</p>
<p>It would also be nice if we could use <a href="http://clojure.org/">Clojure</a> for writing Cocoa apps, but Apple decided to <a href="http://developers.slashdot.org/article.pl?sid=05/07/11/1833252">drop the ball on that one</a>.</p>
<p>However, that doesn&#8217;t mean we still can&#8217;t write good, fast, multithreaded code.</p>
<h3>Actors and Shared Data</h3>
<p>Right now we&#8217;re in the process of rewriting parts of Espionage&#8217;s helper program, which is fairly multithreaded and does most of Espionage&#8217;s heavy-lifting. Currently we are using <b>mutex locks</b> (in the form of NSLock) to synchronize some of the shared data in the application, and while locks are &#8220;OK&#8221;, they can start to get messy when you&#8217;ve got a lot going on.</p>
<p>That&#8217;s why we&#8217;re going to convert the helper to use actors (courtesy of <a href="http://www.plausiblelabs.com/">Plausible Labs</a>&#8216; great <a href="http://code.google.com/p/plactorkit/">PLActorKit</a>). But even when you&#8217;ve structured your code to use the actor approach, you still have a problem if those actors need to operate on data that&#8217;s shared with other actors or other threads. This is where locks could come in, but locks tend to suck.</p>
<p>Locks are slow, everyone knows that, but in our experience they can also encourage bad code because you can associate a lock with just about anything, it doesn&#8217;t have to be a specific piece of data, it can be a group of actions operating on that data, or data related to it. When you don&#8217;t have consistency, things can get out of hand.</p>
<p>So I&#8217;ve written a class that aims to solve these two problems with locks.</p>
<h3>TESharedObject</h3>
<p>When you hold a lock, you prevent any other thread from accessing the data that it&#8217;s protecting, regardless of whether that is necessary or not. What if the data that you&#8217;re protecting is often only read from? Then despite the fact that it&#8217;s perfectly fine for multiple threads to read from a piece of data simultaneously, each reader has to wait in line for the lock to become available. This can really slow things down.</p>
<p>TESharedObject is a replacement for locks that takes this into account. It changes the &#8220;lock&#8221; paradigm in two ways:</p>
<p>First off, it&#8217;s a <b>wrapper around shared data</b>, that is as opposed to a lock, which is just another &#8220;thing&#8221; that you arbitrarily decide is associated with a piece of data, a decision that you may or may not change your mind about as your code evolves.</p>
<p>The other difference is that unlike a lock, it allows multiple readers to access the data at the same time, provided no one&#8217;s writing to it. Databases often take this same approach to improve performance.</p>
<h3>Semaphores</h3>
<p>TESharedObject implements a basic algorithm using the <b>semaphore</b> primitive. Semaphores aren&#8217;t used very often in Cocoa programming, so if you&#8217;re unfamiliar with them you&#8217;ll be forgiven. Quick overview: a semaphore is an entity that has a count associated with it. You can increase the count by calling, say, &#8220;up&#8221; on it, or decrease it by calling &#8220;down&#8221; on it. If you call &#8220;down&#8221; on it when the count is zero, you block until some other thread increases the count.</p>
<p>So, say we have a database, and we want people to be able to read from it safely simultaneously when no one&#8217;s writing to it. By using two semaphores and keeping track of how many people are reading we can accomplish this like so (pseudo-code):</p>
<pre class="code"><span class="source source_objc">semaphore <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span> = <span class="constant constant_numeric constant_numeric_c">1</span>;
semaphore <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span> = <span class="constant constant_numeric constant_numeric_c">1</span>;
<span class="storage storage_type storage_type_c">int</span> readerCount = <span class="constant constant_numeric constant_numeric_c">0</span>;

reader:
    down(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    <span class="keyword keyword_control keyword_control_c">if</span> (++readerCount==<span class="constant constant_numeric constant_numeric_c">1</span>)
        down(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    up(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    access_database();
    down(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    <span class="keyword keyword_control keyword_control_c">if</span> (--readerCount == <span class="constant constant_numeric constant_numeric_c">0</span>)
        up(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    up(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);

writer:
    down(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    access_database();
    up(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);</span></pre>
<p>Here the semaphore <span class="code">sAccess</span> is used as the &#8220;lock&#8221; on the database, or more accurately, to suspend the next thread that calls &#8220;down&#8221; on it. Only the <i style="color:inherit">first</i> reader will call down on <span class="code">sAccess</span>. A second semaphore <span class="code">sRead</span> is used as a backup to <span class="code">sAccess</span> in the situation that another reader is already suspended on <span class="code">sAccess</span>.</p>
<p>The code for the writer is simple, all writers decrement <span class="code">sAccess</span>&#8216;s count, meaning a single writer is enough to stop everyone.</p>
<h3>Building A Better Lock</h3>
<p>Now that we have the pseudo-code, we need a design for our lock, and to get the design we need to have some sort of an idea of how we plan on using this lock in practice. I know! It should look something like this:</p>
<pre class="code"><span class="source source_objc"><span class="support support_class support_class_cocoa">NSMutableString</span> *sharedData = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSMutableString</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringWithString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Poop<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
TESharedObject *superLock = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedObject <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">alloc</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">initWithObject<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>sharedData</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

reader:
    <span class="support support_class support_class_cocoa">NSObject</span> *obj = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>superLock <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">borrowForReading</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>; <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> like "lock"
</span>    <span class="support support_function support_function_cocoa">NSLog</span>(<span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>We've got an object! Take a look: %@<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, obj);
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>superLock <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">returnObject</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>; <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> like "unlock"
</span>
writer:
    <span class="support support_class support_class_cocoa">NSMutableString</span> *aStr = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>superLock <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">borrowForWriting</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>aStr <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Harro!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>superLock <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">returnObject</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;</span></pre>
<p>There, that looks pretty good. Our <span class="code">superLock</span> is bound to the data it&#8217;s protecting. When we want to have a look at the data we call <span class="code">-borrowForReading</span> to &#8220;borrow&#8221; it, and once we&#8217;re finished with it we &#8220;return&#8221; the data by calling <span class="code">-returnObject</span>. Simple enough, and it works just like using a lock. All we have to do is make sure that we don&#8217;t write to the data. If we want to write to it, we call <span class="code">-borrowForWriting</span> instead.</p>
<p>Let&#8217;s have a look at what&#8217;s inside.</p>
<p><b>-borrowForReading</b></p>
<pre class="code"><span class="source source_objc">- (<span class="storage storage_type storage_type_objc">id</span>)borrowForReading
{
    semaphore_wait(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    <span class="keyword keyword_control keyword_control_c">if</span> ( ++readerCount == <span class="constant constant_numeric constant_numeric_c">1</span> )
        semaphore_wait(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    semaphore_signal(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    <span class="keyword keyword_control keyword_control_c">return</span> obj;
}</span></pre>
<p>There&#8217;s our pseudo-code! Well, about half of it, I bet you can guess where the other half is. But before we get to that, let&#8217;s take a look at <span class="code">-borrowForWriting</span>:</p>
<p><b>-borrowForWriting</b></p>
<pre class="code"><span class="source source_objc">- (<span class="storage storage_type storage_type_objc">id</span>)borrowForWriting
{
    semaphore_wait(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    writing = <span class="constant constant_language constant_language_objc">YES</span>;
    <span class="keyword keyword_control keyword_control_c">return</span> obj;
}</span></pre>
<p>Here the code diverges a bit with the introduction of a new variable <span class="code">writing</span>.  We use it so that whether we called <span class="code">-borrowForReading</span> or <span class="code">-borrowForWriting</span>, we only have to call:</p>
<p><b>-returnObject</b></p>
<pre class="code"><span class="source source_objc"><span class="meta meta_implementation meta_implementation_objc"><span class="meta meta_scope meta_scope_implementation meta_scope_implementation_objc"><span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">returnObject</span></span>
</span>{
    <span class="keyword keyword_control keyword_control_c">if</span> ( writing )
    {
        writing = <span class="constant constant_language constant_language_objc">NO</span>;
        semaphore_signal(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
    }
    <span class="keyword keyword_control keyword_control_c">else</span>
    {
        semaphore_wait(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
        <span class="keyword keyword_control keyword_control_c">if</span> ( --readerCount == <span class="constant constant_numeric constant_numeric_c">0</span> )
            semaphore_signal(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sAccess</span>);
        semaphore_signal(<span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sRead</span>);
    }
}</span></span></span></pre>
<p>And that&#8217;s it. We&#8217;re almost done now, if you&#8217;ve made it here, thanks for sticking with me. I only have two more things to show you, and I think it&#8217;ll be worth it.</p>
<h3>TESharedMap</h3>
<p>Another aspect of shared data that we&#8217;ve neglected to address is the notion of &#8220;globality&#8221;. Yes, I did just make that word up, but it has <i>important consequences!</i> When you&#8217;re dealing with shared data, you&#8217;re often dealing with global variables, and dammit, now you&#8217;ve gotta find a place to put them!</p>
<p>A lot of people just put them at the top. They make long laundry lists of static declarations at the top of some file, and for each piece of shared data two declarations are required: the data, and the lock for the data. This can get kinda ugly, and ugly code is often harder to read and maintain. Our TESharedObject suffers from this same problem, it&#8217;d be nice if we could just focus on the data and not have to deal with the lock that&#8217;s associated with it.</p>
<p>We can get close to this with <b>TESharedMap</b>. TESharedMap acts as a &#8220;summoner&#8221;, we tell it: &#8220;Give us our object!&#8221; And it does. We don&#8217;t need to worry about keeping track of the associated TESharedObject, TESharedMap handles that for us. Put something into the map and it magically becomes thread-safe, so long as you remember to retrieve it only through the map.</p>
<p>Here&#8217;s its interface:</p>
<pre class="code"><span class="source source_objc"><span class="meta meta_interface-or-protocol meta_interface-or-protocol_objc"><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>interface</span> <span class="entity entity_name entity_name_type entity_name_type_objc">TESharedMap</span> <span class="punctuation punctuation_definition punctuation_definition_entity punctuation_definition_entity_other punctuation_definition_entity_other_inherited-class punctuation_definition_entity_other_inherited-class_objc">:</span> <span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_objc">NSObject</span><span class="meta meta_divider meta_divider_objc"> </span><span class="meta meta_scope meta_scope_interface meta_scope_interface_objc">{
    TESharedObject *sharedMap;
}

<span class="meta meta_function meta_function_objc">+ <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span>TESharedMap *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">map</span></span>;</span>

<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">id</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">borrowObjectForKey</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="support support_class support_class_cocoa">NSString</span> *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">key</span></span> <span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc">forReadingOnly</span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">BOOL</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">readonly</span></span>;</span>
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">returnObjectForKey</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="support support_class support_class_cocoa">NSString</span> *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">key</span></span>;</span>
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">setObject</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">id</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">obj</span></span> <span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc">forKey</span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="support support_class support_class_cocoa">NSString</span> *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">key</span></span>;</span>
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">removeObjectForKey</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="support support_class support_class_cocoa">NSString</span> *<span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">key</span></span>;</span>

</span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>end</span></span></span></pre>
<h3>Benchmarks</h3>
<p>What are the performance benefits of using TESharedObject and TESharedMap instead of NSLock and the like? For this I&#8217;ve written 3 programs, they each do the same thing, the only difference is that each uses a different synchronization primitive that we&#8217;ve discussed (TESharedObject, TESharedMap, and NSLock).</p>
<p>Here&#8217;s the TESharedMap version:</p>
<pre class="code" style="height:500px; overflow:auto;"><span class="source source_objc"><span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_other string_quoted_other_lt-gt string_quoted_other_lt-gt_include string_quoted_other_lt-gt_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">&lt;</span>Foundation/Foundation.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">&gt;</span></span></span>
<span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_double string_quoted_double_include string_quoted_double_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>TESharedObject.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span></span>
<span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_double string_quoted_double_include string_quoted_double_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Common.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span></span>
<span class="meta meta_preprocessor meta_preprocessor_c meta_preprocessor_c_include">#<span class="keyword keyword_control keyword_control_import keyword_control_import_include keyword_control_import_include_c">import</span> <span class="string string_quoted string_quoted_double string_quoted_double_include string_quoted_double_include_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Config.h<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span></span>

<span class="storage storage_modifier storage_modifier_c">static</span> <span class="storage storage_type storage_type_c">int</span> reader = <span class="constant constant_numeric constant_numeric_c">0</span>;
<span class="storage storage_modifier storage_modifier_c">static</span> <span class="storage storage_type storage_type_c">int</span> writer = <span class="constant constant_numeric constant_numeric_c">0</span>;
<span class="storage storage_modifier storage_modifier_c">static</span> <span class="storage storage_type storage_type_c">int</span> msgIdx = <span class="constant constant_numeric constant_numeric_c">0</span>;
<span class="storage storage_modifier storage_modifier_c">static</span> <span class="storage storage_type storage_type_c">int</span> tCount = NUM_READERS + NUM_WRITERS;

<span class="storage storage_modifier storage_modifier_c">static</span> <span class="support support_class support_class_cocoa">NSString</span> *msgs<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> = {
    <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Hello World!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>how are you?<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>random message!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>hope we have enough of these...<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>,
    <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>I'm sure we will<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>there so many!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>How many messages does it take<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>to screw in a lightbulb?<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>
};

<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">newMsgIdx</span> (msgIdx++%(<span class="keyword keyword_operator keyword_operator_sizeof keyword_operator_sizeof_c">sizeof</span>(msgs)/<span class="keyword keyword_operator keyword_operator_sizeof keyword_operator_sizeof_c">sizeof</span>(msgs<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="constant constant_numeric constant_numeric_c">0</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>)))</span>

<span class="meta meta_interface-or-protocol meta_interface-or-protocol_objc"><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>interface</span> <span class="entity entity_name entity_name_type entity_name_type_objc">Actor</span> <span class="punctuation punctuation_definition punctuation_definition_entity punctuation_definition_entity_other punctuation_definition_entity_other_inherited-class punctuation_definition_entity_other_inherited-class_objc">:</span> <span class="entity entity_other entity_other_inherited-class entity_other_inherited-class_objc">NSObject</span><span class="meta meta_divider meta_divider_objc">
</span><span class="meta meta_scope meta_scope_interface meta_scope_interface_objc"><span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">readerMain</span></span>;</span>
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">writerMain</span></span>;</span>
</span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>end</span></span>

<span class="meta meta_implementation meta_implementation_objc"><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>implementation</span> <span class="entity entity_name entity_name_type entity_name_type_objc">Actor</span>
<span class="meta meta_scope meta_scope_implementation meta_scope_implementation_objc"><span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">readerMain</span></span>
</span>{
    <span class="support support_class support_class_cocoa">NSAutoreleasePool</span> *pool = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSAutoreleasePool</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">new</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

    <span class="storage storage_type storage_type_c">int</span> i=READ_TIMES, readerID = ++reader;

    <span class="keyword keyword_control keyword_control_c">while</span> ( --i &gt; <span class="constant constant_numeric constant_numeric_c">0</span> )
    {
        <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Reader <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> getting message...<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, readerID);
        <span class="support support_class support_class_cocoa">NSString</span> *message = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedMap <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">map</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">borrowObjectForKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>OBJ_KEY <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">forReadingOnly<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">YES</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
        <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Reader <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> got message: <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%s</span><span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, readerID, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>message <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">UTF8String</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>);
        usleep(READ_SLEEP);
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedMap <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">map</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">returnObjectForKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>OBJ_KEY</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    }

    <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Reader <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> done!<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, readerID);
    <span class="keyword keyword_control keyword_control_c">if</span> ( --tCount == <span class="constant constant_numeric constant_numeric_c">0</span> )
    {
        <span class="support support_function support_function_C99 support_function_C99_c">printf</span>(<span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>good-bye<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);
        <span class="support support_function support_function_C99 support_function_C99_c">exit</span>(<span class="constant constant_numeric constant_numeric_c">0</span>);
    }
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>pool <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">release</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}
<span class="meta meta_function meta_function_objc">- <span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_c">void</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">writerMain</span></span>
</span>{
    <span class="support support_class support_class_cocoa">NSAutoreleasePool</span> *pool = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSAutoreleasePool</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">new</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

    <span class="storage storage_type storage_type_c">int</span> i=WRITE_TIMES, writerID = ++writer;

    <span class="keyword keyword_control keyword_control_c">while</span> ( --i &gt; <span class="constant constant_numeric constant_numeric_c">0</span> )
    {
        <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Writer <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> getting message...<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, writerID);
        <span class="support support_class support_class_cocoa">NSMutableString</span> *message = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedMap <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">map</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">borrowObjectForKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>OBJ_KEY <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">forReadingOnly<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>WRITE_MEANS_READ</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>message <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>msgs<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>newMsgIdx<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
        <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Writer <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> set message to: <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%s</span><span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, writerID, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>message <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">UTF8String</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>);
        usleep(WRITE_SLEEP);
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedMap <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">map</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">returnObjectForKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>OBJ_KEY</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    }

    <span class="support support_function support_function_C99 support_function_C99_c">fprintf</span>(stderr, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>Writer <span class="constant constant_other constant_other_placeholder constant_other_placeholder_c">%d</span> done!<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>, writerID);
    <span class="keyword keyword_control keyword_control_c">if</span> ( --tCount == <span class="constant constant_numeric constant_numeric_c">0</span> )
    {
        <span class="support support_function support_function_C99 support_function_C99_c">printf</span>(<span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>good-bye<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);
        <span class="support support_function support_function_C99 support_function_C99_c">exit</span>(<span class="constant constant_numeric constant_numeric_c">0</span>);
    }
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>pool <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">release</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}
</span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>end</span></span>

<span class="storage storage_type storage_type_c">int</span><span class="meta meta_function meta_function_c"> <span class="entity entity_name entity_name_function entity_name_function_c">main</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span><span class="storage storage_type storage_type_c">int</span> argc, <span class="storage storage_type storage_type_c">char</span> <span class="storage storage_modifier storage_modifier_c">const</span> *argv<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">)</span></span>
{
    <span class="support support_class support_class_cocoa">NSAutoreleasePool</span> *pool = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSAutoreleasePool</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">new</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

    <span class="support support_class support_class_cocoa">NSMutableString</span> *message = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSMutableString</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">alloc</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">initWithString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>msgs<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>newMsgIdx<span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>TESharedMap <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">map</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setObject<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>message <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">forKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>OBJ_KEY</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

    <span class="keyword keyword_control keyword_control_c">for</span> (<span class="storage storage_type storage_type_c">int</span> i=<span class="constant constant_numeric constant_numeric_c">0</span>; i&lt;NUM_READERS; ++i)
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSThread</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">detachNewThreadSelector<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>selector</span>(readerMain) <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">toTarget<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>Actor <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">new</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">withObject<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">nil</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="keyword keyword_control keyword_control_c">for</span> (<span class="storage storage_type storage_type_c">int</span> i=<span class="constant constant_numeric constant_numeric_c">0</span>; i&lt;NUM_WRITERS; ++i)
        <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSThread</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">detachNewThreadSelector<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="storage storage_type storage_type_objc"><span class="punctuation punctuation_definition punctuation_definition_storage punctuation_definition_storage_type punctuation_definition_storage_type_objc">@</span>selector</span>(writerMain) <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">toTarget<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>Actor <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">new</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span> <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">withObject<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">nil</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> wait for threads to terminate...
</span>    <span class="keyword keyword_control keyword_control_c">while</span> (tCount)
        sleep(<span class="constant constant_numeric constant_numeric_c">1</span>);

    <span class="support support_function support_function_C99 support_function_C99_c">printf</span>(<span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>good-bye<span class="constant constant_character constant_character_escape constant_character_escape_c">\n</span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span>pool <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">release</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
    <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_numeric constant_numeric_c">0</span>;
}</span></code></pre>
<p>The program launches a certain number of readers and writers, and they each access an NSMutableString a certain number of times. To simulate computation, each reader and writer sleeps for a certain amount of time upon accessing the string. The number of readers and writers, as well as other parameters, can be adjusted by modifying the &#8220;Config.h&#8221; file:</p>
<pre class="code"><span class="source source_objc"><span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> play with these parameters
</span><span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">NUM_READERS</span> <span class="constant constant_numeric constant_numeric_c">4</span></span>
<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">NUM_WRITERS</span> <span class="constant constant_numeric constant_numeric_c">4</span></span>
<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">READ_TIMES</span> <span class="constant constant_numeric constant_numeric_c">4000</span></span>
<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">WRITE_TIMES</span> <span class="constant constant_numeric constant_numeric_c">4000</span></span>
<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">READ_SLEEP</span> <span class="constant constant_numeric constant_numeric_c">1000</span></span>
<span class="meta meta_preprocessor meta_preprocessor_macro meta_preprocessor_macro_c">#<span class="keyword keyword_control keyword_control_import keyword_control_import_define keyword_control_import_define_c">define</span> <span class="entity entity_name entity_name_function entity_name_function_preprocessor entity_name_function_preprocessor_c">WRITE_SLEEP</span> <span class="constant constant_numeric constant_numeric_c">1000</span></span></span></pre>
<p>I ran 4 benchmarks using the *NIX &#8216;time&#8217; command comparing the 3 synchronization primitives against each other by adjusting the number of readers and writers and keeping the other parameters constant.</p>
<p><b>Dramatic Results</b></p>
<p><center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2009/08/TESharedObject-results.png" alt="TESharedObject results" title="TESharedObject results" width="411" height="286" class="alignnone size-full wp-image-912" /></center></p>
<p>First we see that the extra layer that TESharedMap adds on top of TESharedObject is pretty much negligible in terms of performance.</p>
<p>The results for <b>0r/4w</b> is the worst-case scenario for TESharedObject (no readers), and as expected it performs pretty much exactly like the typical lock.</p>
<p>The results for <b>4r/0w</b> is the best-case scenario, when there are only readers accessing the data. This is the real payoff, <b>almost no penalty for accessing shared data!</b> You can&#8217;t get this with mutex locks.</p>
<p>The other two results show what happens when you have both readers and writers, in which case TESharedObject quickly overtakes the mutex lock, but what&#8217;s most interesting is that as you add more readers, TESharedObject takes a fairly negligible hit while the lock&#8217;s performance is significantly degraded. Why?</p>
<p>The reason becomes pretty obvious if you actually run these tests yourself. What happens is that the readers dominate the lock. This happens because in this program, the data is besieged by a constant and unrelenting stream of readers and writers who lust after the data until they&#8217;ve had their fill. In this situation, the more readers you add, the less likely it becomes that a writer will be able to get a hold of it, so what happens is that there&#8217;s suddenly a stampede of readers with virtually unfettered access to the data which they quickly gobble up, and then after most or all of the readers have had their fill the writers get their turn.</p>
<p>So while TESharedObject can provide a significant performance boost, if your lock is highly contested by readers they can shut out any writers. In most of the situations that I&#8217;ve seen locks used, this doesn&#8217;t happen. But if you are using a TESharedObject in a maelstrom like this, you&#8217;ll probably want to subclass it and modify the <span class="code">-borrowForReading</span> method so that it sleeps if the <span class="code">readerCount</span> is too high, which will make it a bit slower, but it will still be at least as fast as a lock, and you&#8217;ll have better looking code.</p>
<p>I think that&#8217;s it for now. All the code in this post, including the code for TESharedObject and TESharedMap, is provided under an BSD-style license and can be downloaded by clicking the icon below:</p>
<p><a href="/other/TESharedObject.zip" style="border:none"><img src="http://www.taoeffect.com/blog/wp-content/uploads/2009/08/TESharedObject.png" alt="TESharedObject" title="TESharedObject" width="137" height="65" class="alignnone size-full wp-image-887" /></a></p>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>- Greg (twitter: @<a href="http://twitter.com/taoeffect">taoeffect</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/08/building-a-better-lock-tesharedobject/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wireless Sleeper Updated</title>
		<link>http://www.taoeffect.com/blog/2009/08/wireless-sleeper-updated/</link>
		<comments>http://www.taoeffect.com/blog/2009/08/wireless-sleeper-updated/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 03:49:47 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[wireless sleeper]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=821</guid>
		<description><![CDATA[Wireless Sleeper, my fix for the insomnia affecting many wireless-capable laptops, has been updated to support Apple&#8217;s next operating system, Snow Leopard. A separate, Snow Leopard-only version must be downloaded. Enjoy! Click to download.]]></description>
			<content:encoded><![CDATA[<p><a href="/blog/2009/01/wireless-sleeper-fixin-apples-bugs/">Wireless Sleeper</a>, my fix for the insomnia affecting many wireless-capable laptops, has been updated to support Apple&#8217;s next operating system, <b>Snow Leopard</b>. A separate, Snow Leopard-only version must be downloaded.</p>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><a href="http://www.taoeffect.com/sleeper/sleeper_sl.zip">Click to download.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/08/wireless-sleeper-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cloak contest over!</title>
		<link>http://www.taoeffect.com/blog/2009/07/cloak-contest-over/</link>
		<comments>http://www.taoeffect.com/blog/2009/07/cloak-contest-over/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 01:21:29 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Espionage]]></category>
		<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[cloak]]></category>
		<category><![CDATA[contest]]></category>
		<category><![CDATA[greg]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=783</guid>
		<description><![CDATA[Thank you to everyone who submitted icons for the Cloak icon contest! The contest is over, and my apologies for being two days late to the announcement. The bad news is that we weren&#8217;t able to pick a winner, meaning Cloak will continue to use the same icon for the time being. The good news [...]]]></description>
			<content:encoded><![CDATA[<p>Thank you to everyone who submitted icons for the <a href="/blog/2009/06/cloak-11-artists-win-an-espionage-license/">Cloak icon contest</a>!</p>
<p>The contest is over, and my apologies for being <i style="color:inherit">two days</i> late to the announcement.</p>
<p>The bad news is that we weren&#8217;t able to pick a winner, meaning Cloak will continue to use the same icon for the time being. The good news though is that I&#8217;m throwing the entire concept of having a contest out the window.  If you think you can improve upon <a href="/blog/2009/05/cloak-manage-your-invisible-files/">Cloak&#8217;s</a> icon, by all means go for it and post your creation in the comments below.  You may want to read some of the <a href="/blog/2009/06/cloak-11-artists-win-an-espionage-license/#comments">comments</a> posted to the contest before doing so though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/07/cloak-contest-over/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cloak contest ends soon!</title>
		<link>http://www.taoeffect.com/blog/2009/06/cloak-contest-ends-soon/</link>
		<comments>http://www.taoeffect.com/blog/2009/06/cloak-contest-ends-soon/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 20:45:54 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Espionage]]></category>
		<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[cloak]]></category>
		<category><![CDATA[contest]]></category>
		<category><![CDATA[greg]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=716</guid>
		<description><![CDATA[The chance to win a license to Espionage (or equivalent value) is fast approaching, and thanks to the obscurity of the contest your chances of winning are great! If you have the skills to improve upon Cloak&#8216;s icon, go for it! Contest ends next Tuesday, June 30th.]]></description>
			<content:encoded><![CDATA[<p>The chance to <a href="/blog/2009/06/cloak-11-artists-win-an-espionage-license/">win a license to Espionage</a> (or equivalent value) is fast approaching, and thanks to the obscurity of the contest your chances of winning are great! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  If you have the skills to improve upon <a href="/blog/2009/05/cloak-manage-your-invisible-files/">Cloak</a>&#8216;s icon, go for it!</p>
<p>Contest ends next Tuesday, June 30th.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/06/cloak-contest-ends-soon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cloak 1.1! + Artists: Win an Espionage license!</title>
		<link>http://www.taoeffect.com/blog/2009/06/cloak-11-artists-win-an-espionage-license/</link>
		<comments>http://www.taoeffect.com/blog/2009/06/cloak-11-artists-win-an-espionage-license/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 18:29:18 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Espionage]]></category>
		<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[cloak]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=582</guid>
		<description><![CDATA[Cloak has been updated to 1.1 (download) and this brings two much needed improvements: Mac OS X 10.4 support, and an icon! Yes, the new icon looks like it&#8217;s out of a video game.. I swear I&#8217;m a much better coder than I am an artist! Unfortunately John has too much on his plate right [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/blog/2009/05/cloak-manage-your-invisible-files/">Cloak</a> has been updated to 1.1 (<a href="/cloak/Cloak.zip">download</a>) and this brings two much needed improvements: <b>Mac OS X 10.4 support</b>, and <b>an icon!</b></p>
<p><center><img src="/includes/images/Cloak_icon.png"></center></p>
<p>Yes, the new icon looks like it&#8217;s out of a video game.. I swear I&#8217;m a much better coder than I am an artist!  Unfortunately John has too much on his plate right now and therefore cannot give Cloak a proper icon, which is why I&#8217;m holding a contest:</p>
<h4>Win an Espionage license! (Or $24.95)</h4>
<p>Cloak needs a nice 512&#215;512 icon of a cloaked figure with glowing eyes. If you think you can do a better job we welcome you to try, just post a link to your icon in the comments below.</p>
<p>The winner will get to choose his or her prize: <b>a free license to <a href="/espionage">Espionage</a> or $24.95 via PayPal</b>. Additionally, your name will be placed in Cloak&#8217;s about box with an optional link to your site.</p>
<p>Please remember to enter a real email address when posting a comment so that we know where to reach you.</p>
<p>The winner (if there is one), will be announced at the end of the month, <b>June 30th, 2009</b>.</p>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><a href="/cloak/Cloak.zip" style="border:none"><img src="/includes/images/cloak_dl.png"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/06/cloak-11-artists-win-an-espionage-license/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>ebswitch: EventBox Profile Switcher</title>
		<link>http://www.taoeffect.com/blog/2009/05/ebswitch-eventbox-profile-switcher/</link>
		<comments>http://www.taoeffect.com/blog/2009/05/ebswitch-eventbox-profile-switcher/#comments</comments>
		<pubDate>Tue, 26 May 2009 22:30:55 +0000</pubDate>
		<dc:creator>Greg Slepak</dc:creator>
				<category><![CDATA[Free Stuff]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ebswitch]]></category>
		<category><![CDATA[eventbox]]></category>
		<category><![CDATA[greg]]></category>
		<category><![CDATA[newLISP]]></category>

		<guid isPermaLink="false">http://www.taoeffect.com/blog/?p=542</guid>
		<description><![CDATA[My favorite Twitter client is EventBox by The Cosmic Machine. And while it has a million great features like support for Instapaper and a great interface, it&#8217;s missing one critical piece of functionality and that is support for multiple profiles. However, it&#8217;s still possible to use EventBox with multiple profiles, but perhaps not at the [...]]]></description>
			<content:encoded><![CDATA[<p>My favorite Twitter client is <b>EventBox</b> by <a href="http://thecosmicmachine.com/">The Cosmic Machine</a>. And while it has a million great features like support for <a href="http://www.instapaper.com/">Instapaper</a> and a great interface, it&#8217;s missing one critical piece of functionality and that is support for multiple profiles. However, it&#8217;s still possible to use EventBox with multiple profiles, but perhaps not at the same time. </p>
<p>One solution is a great little program called <a href="http://roobasoft.com/rooSwitch/">rooSwitch</a>. It can be used with EventBox to give you the ability to switch between different isolated profiles, each with its own settings. You could configure rooSwitch with multiple EventBox profiles, say for example one for each Twitter account that you use:<br />
<center><img src="http://www.taoeffect.com/blog/wp-content/uploads/2009/05/rooswitch.png" alt="rooSwitch with two twitter profiles" title="rooSwitch with two twitter profiles" width="387" height="366"/></center></p>
<p>While rooSwitch is great, I don&#8217;t have much use for it besides switching EventBox profiles, and I&#8217;m a terminal fiend anyway, so I wrote a simple <a href="http://www.newlisp.org">newLISP</a> script called <b>ebswitch</b> that does this for me.  Here&#8217;s an example session:</p>
<pre class="code"><b>$ ebswitch</b>
ebswitch version 0.2
Usage: /usr/local/bin/ebswitch twitter_profile_name
<b>$ ebswitch espionageapp</b>
taoeffect => espionageapp
Creating fresh account for: espionageapp
Successfully switched to profile: espionageapp
    <i>... EventBox opens, enter 'espionageapp' login information ...</i>
<b>$ ebswitch taoeffect</b>
Quit EventBox? [y|n]: y
espionageapp => taoeffect
Successfully switched to profile: taoeffect</pre>
<h4>Installing ebswitch</h4>
<p>ebswitch is a <a href="http://www.newlisp.org">newLISP</a> script, so to use it you&#8217;ll need to make sure that newLISP is installed (<a href="http://www.newlisp.org/downloads/newlisp-10.0.2-intel.dmg">Intel</a>/<a href="http://www.newlisp.org/downloads/newlisp-10.0.2-ppc.dmg">PPC</a>), and don&#8217;t worry, one of the great things about newLISP is how small it is. Then, after <a href="/other/ebswitch.lsp.zip">downloading</a> ebswitch to your Desktop, install it into your /usr/local/bin (or /usr/bin) like so:</p>
<pre class="code">$ cd ~/Desktop
$ sudo install ebswitch.lsp /usr/local/bin/ebswitch
Password: <i>enter admin password</i></pre>
<p>Enjoy! <img src='http://www.taoeffect.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><b>Update:</b> ebswitch 0.2 adds more intelligence and can now quit EventBox for you.</p>
<p><a href="/other/ebswitch.lsp.zip" style="border:none"><img src="http://www.taoeffect.com/blog/wp-content/uploads/2009/05/eb_switch.png" alt="eb_switch.lsp" title="eb_switch.lsp"/></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.taoeffect.com/blog/2009/05/ebswitch-eventbox-profile-switcher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

