<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Generalities &amp; Details: Adventures in the High-tech Underbelly</title>
    <link>http://www.bluebytesoftware.com/blog/</link>
    <description>Joe Duffy's Weblog</description>
    <language>en-us</language>
    <copyright>Joe Duffy</copyright>
    <lastBuildDate>Wed, 24 Jun 2009 03:13:52 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.8.5223.2</generator>
    <managingEditor>joe@bluebytesoftware.com</managingEditor>
    <webMaster>joe@bluebytesoftware.com</webMaster>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=652962f1-5073-49a4-b233-9ca24b494742</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,652962f1-5073-49a4-b233-9ca24b494742.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,652962f1-5073-49a4-b233-9ca24b494742.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=652962f1-5073-49a4-b233-9ca24b494742</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <title>Concurrency and exceptions</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,652962f1-5073-49a4-b233-9ca24b494742.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/06/24/ConcurrencyAndExceptions.aspx</link>
      <pubDate>Wed, 24 Jun 2009 03:13:52 GMT</pubDate>
      <description>&lt;p&gt;
   I wrote this memo&amp;nbsp;over 2 1/2&amp;nbsp;years ago about what to do with concurrent
   exceptions in Parallel Extensions to .NET.&amp;nbsp; Since &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ee2118cc-51cd-46ad-ab17-af6fff7538c9&amp;amp;displaylang=en"&gt;Beta1
   is now out&lt;/a&gt;, I thought posting it may provide some insight into our design decisions.&amp;nbsp;
   (And yes, most design discussions start this way.&amp;nbsp; Somebody develops a personal
   itch, dives deep into it, and emerges with a proposal for others to vote up, shoot
   down, or, as is typically the case, somewhere in the middle (provide constructive
   feedback, iterate, etc).)&amp;nbsp; I've made only a few slight edits (like replacing
   code- and type-names), but it's mainly in original form.&amp;nbsp; I still agree with
   much of what I wrote, although I'd definitely write it differently today.&amp;nbsp; And
   in retrospect, I would have driven harder to get deeper runtime integration.&amp;nbsp;
   Perhaps in the next release.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;~~~&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;em&gt;&lt;strong&gt;Concurrency and Exceptions&lt;/strong&gt;
   &lt;br&gt;
   October, 2006&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
   Exceptions raised inside of concurrent workers must be dealt with in a deliberate
   way.&amp;nbsp; Failures can happen concurrently, and yet often the programmer is working
   with an API that appears to them as though it’s sequential.&amp;nbsp; The basic question
   is, then, how do we communicate failure?
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;The problem&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   Fork/join concurrency, in which a single “master” thread forks and coordinates with
   N separate parallel workers, is an incredibly common instance of one of these sequential-looking
   concurrent operations.&amp;nbsp; The same callback is run by many threads at once, and
   may fail zero, one, or multiple times.&amp;nbsp; The exception propagation problem is
   inescapable here and comes with a lot of expectations, because the programmer is presented
   a traditional stack-based function calling interface papered on top of data or task
   parallelism underneath.
&lt;/p&gt;
&lt;p&gt;
   I am faced with&amp;nbsp;the need for a solution to this problem for PLINQ right now&amp;nbsp;and,
   while I could invent a one-off solution, we owe it to our customers to come up with
   a common platform-wide approach (or at least ManyCore-wide).&amp;nbsp; Any solution should
   compose well across the stack, so that somebody invoking a PLINQ query from within
   their TPL task that was spawned from a thread pool thread yields the expected and
   consistent result.&amp;nbsp; And I would like for us to reach consensus for both managed
   and native programming models.
&lt;/p&gt;
&lt;p&gt;
   Before moving on, there is one non-goal to call out.&amp;nbsp; Long-running tasks not
   under the category of fork/join also deserve some attention, because of the ease with
   which stack traces can be destroyed and the corresponding impact to debugging, but
   I will ignore them for now.&amp;nbsp; The problem is not new, exists with the IAsyncResult
   pattern,&amp;nbsp;and PLINQ doesn’t use this sort of singular asynchronous&amp;nbsp;concurrency.&amp;nbsp;
   These cases can typically be trivially solved using existing mechanisms, like standard
   exception marshaling.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;No errors, one error, many errors&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   To understand the core of the issue, imagine we have an API ‘void ForAll&amp;lt;T&amp;gt;(Action&amp;lt;T&amp;gt;
   a, T[] d)’.&amp;nbsp; It takes a delegate and an array, and for every element ‘e’ in ‘d’
   invokes the delegate, passing the element, i.e. ‘a(e)’.&amp;nbsp; If multiple processors
   are available, the implementation of ForAll may use some heuristic to distribute work
   among several OS threads, for instance by partitioning the array, probably running
   one partition on the caller’s thread, and finally joining with these threads before
   returning so that the caller knows that all of the work is complete when the API returns.
&lt;/p&gt;
&lt;p&gt;
   ForAll is not fictitious, and is similar to a number of PLINQ APIs: Where, Select,
   Join, Sort, etc.&amp;nbsp; It is also exposed directly by the TPL runtime’s Parallel class
   which intelligently forks and joins with workers.
&lt;/p&gt;
&lt;p&gt;
   ‘a’ is a user-specified delegate and can do just about anything.&amp;nbsp; That includes,
   of course, throwing an exception.&amp;nbsp; What’s worse, because ‘a’ is run in several
   threads concurrently, there may be more than one exception thrown.&amp;nbsp; In fact,
   there are three distinct possibilities:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      No errors: No invocations of ‘a’ throw an exception. 
   &lt;li&gt;
      One error: A single invocation of ‘a’ throws an exception. 
   &lt;li&gt;
      Many errors: Concurrent invocations of ‘a’ on separate threads throw exceptions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   Clearly letting an exception crash whichever thread the problematic ‘a(e)’ happened
   to be run on is problematic and confusing.&amp;nbsp; If for no other reason than the IAsyncResult
   pattern has established precedent.&amp;nbsp; But realistically, the developer would be
   forced to devise his or her own scheme to marshal the failure back to the calling
   thread in order for any sort of chance at recovery.&amp;nbsp; They would get it wrong
   and it would lead to incompatible and poorly composing silos over time.&amp;nbsp; A Byzantine
   model that fully prohibits exceptions passing fork/join barriers goes against the
   simple, familiar, and understandable (albeit often deceptively so) model of exceptions.
&lt;/p&gt;
&lt;p&gt;
   (That said, marshaling leads to a crappy debugging experience.&amp;nbsp; An already attached
   debugger will get a break-on-throw notification at the exception on the origin thread,
   but since we catch, marshal, and (presumably) rethrow, the first and second chances
   for unhandled exceptions won’t happen until after the exception been marshaled.&amp;nbsp;
   This breaks the first pass, and by the time the debugger breaks in, or a crash dump
   is taken, the stack associated with the origin thread is apt to have gone away, been
   reused for another task (in the case of the thread pool), etc.&amp;nbsp; We generally
   try to avoid breaking the first pass in the .NET Framework, but do it in plenty of
   places: the BCL today already contains tons of try { … } catch { /*cleanup */ throw;
   }-style exception handlers, for example.&amp;nbsp; For this reason I’m not terribly distraught
   over the implications of doing it ourselves.&amp;nbsp; And sans deeper integration with
   the exception subsystem – something we ought to consider – there aren’t many reasonable
   alternatives.)
&lt;/p&gt;
&lt;p&gt;
   What makes this problem really bad is that ForAll appears as though it’s synchronous:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;void
   f() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // do some stuff&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   ForAll(…, …);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // do some more stuff, ‘ForAll’ is completely done&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The method call to ForAll itself is synchronous, but of course its internal execution
   is not.&amp;nbsp; But still, to the developer, the call to this function represents one
   task, one logical piece of work, regardless of the fact that the implementation uses
   multiple threads for execution.&amp;nbsp; As higher level APIs are built atop things like
   ForAll, the low level parallel infrastructure problem becomes a higher level library
   or application problem.&amp;nbsp; A Sort that is internally parallel must now decide what
   exception(s) it will tell callers it may throw.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;Nondeterministic exception ordering&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   We assume the ForAll API stops calling ‘a(e)’ on any given thread when it first encounters
   an exception.&amp;nbsp; That is, each thread just does something like this:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;for
   (int i = start_idx; i &amp;lt; end_idx; i++) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   a(d[i]);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The for loop terminates when any single iteration throws an exception.&amp;nbsp; Imagine
   our array contains 2048 elements and that ForAll smears the data across 8 threads,
   partitioning the array into 256-element sized chunks of contiguous elements.&amp;nbsp;
   So partition 0 gets elements [0…256), partition 1 gets [256…512), …, and partition
   7 gets [1792…2048).&amp;nbsp; Now imagine that ‘a’ throws an exception whenever fed a
   null element, and that every 256th element in ‘d’, starting at element 10, is null.&amp;nbsp;
   What can a developer reasonably expect to happen?
&lt;/p&gt;
&lt;p&gt;
   On one hand, if we’re trying to preserve the illusion of sequential execution, we
   would only want to surface the exception from the 10th element.&amp;nbsp; With a sequential
   loop, this would have prevented the 266th, 522nd, and so on, elements from even being
   passed to ‘a’.&amp;nbsp; So we might simply say that the “left most” exception (based
   on ordinal index) is the one that gets propagated.&amp;nbsp; The obvious problem with
   this is there are races involved: subsequent iterations indeed may have actually run.&amp;nbsp;
   Alternatively, we might consider only letting the “first” propagate.&amp;nbsp; Unfortunately,
   that doesn’t work either, because we unfortunately can’t necessarily determine, for
   a set of concurrent exceptions, which got thrown first.&amp;nbsp; Even if they have timestamps,
   they could occur in parallel at indistinguishably close times.&amp;nbsp; Nor does this
   really matter, because it feels fundamentally wrong.
&lt;/p&gt;
&lt;p&gt;
   The reason is that we can’t simply throw away failures without true recoverability
   in the system, a la STM.&amp;nbsp; The execution of code leading up to the exception did
   actually happen, after all, and there could be residual effects.&amp;nbsp; We might be
   masking a terrible problem by throwing failures away, possibly leading to (more) state
   corruption and (prolonged, perhaps unrecoverable) damage.&amp;nbsp; What if the 10th element
   was a simple ArgumentNullException that the caller chooses to tolerate, but the 266th
   element’s exception was in response to a catastrophic error from which the application
   can’t recover?&amp;nbsp; We can’t choose to propagate the 10th but swallow the 266th.&amp;nbsp;
   Broadly accepted exceptions best practices suggest that app and library devs never
   catch and swallow exceptions they cannot reasonably handle.&amp;nbsp; We should do our
   best to follow the spirit of this guidance too.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;Re-propagation&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   We could employ an approach similar to the IAsyncResult pattern, with some slight
   tweaks.
&lt;/p&gt;
&lt;p&gt;
   If each concurrent copy of ForAll caught any unhandled exceptions and marshaled them
   to the forking thread, including any exceptions that happen on the forking thread
   itself, we could then propagate all of them together after the join completes.&amp;nbsp;
   The question is then: what exactly do we propagate?
&lt;/p&gt;
&lt;p&gt;
   If there is just a single exception, it’s tempting to just rethrow it.&amp;nbsp; But I
   don’t believe this is a good approach for two primary reasons:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      This will destroy the stack trace of the original exception.&amp;nbsp; This means no information
      about the actual source of the error inside ‘a’ is available.&amp;nbsp; With some help
      from the CLR team, we might be able to get a special type of ‘rethrow’ that copied
      the original stack trace before recreating a new one.&amp;nbsp; This is already done for
      remoted exceptions, and the Exception base class will prefix the original remoted
      stack trace to the new stack trace. 
   &lt;li&gt;
      This doesn’t scale to handle multiple exceptions.&amp;nbsp; If we could solve #1, it might
      be attractive because it appears as-if things happened sequentially, but we can’t
      escape #2, no matter what we do.&amp;nbsp; We could have different behavior in these two
      cases, but I believe it’s better to remain consistent instead.&amp;nbsp; Otherwise, developers
      will need to write their exception handles two ways: one way to handle singular cases,
      and the other way to handle multiple cases, where the same API may do either nondeterministically.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   Given that we need to propagate multiple exceptions, we should wrap them in an aggregate
   exception object, and propagate that instead.&amp;nbsp; At least this way, the original
   exceptions will be preserved, stack trace and all.&amp;nbsp; Of course the original exceptions
   themselves might be other aggregates, handling arbitrary composition.
&lt;/p&gt;
&lt;p&gt;
   For sake of discussion, call this aggregate exception System.AggregateException, which
   of course derives from System.Exception.&amp;nbsp; It exposes the raw Exception objects
   thrown by the threads, via an ‘Exception[] InnerExceptions’ property, and additional
   meta-data about each exception: from which thread it was thrown, and any API specific
   information about the concurrent operation itself.&amp;nbsp; This last part is just to
   help debuggability.&amp;nbsp; For instance, we might tell the developer that the ArgumentNullException
   was thrown from a thread pool thread with ID 1011, and that it occurred while invoking
   the 266th element ‘e’ of array ‘d’.&amp;nbsp; We might also guarantee the exceptions will
   be stored in the order in which they were marshaled back to the forking thread, just
   to help the developer (as much as we can) piece together the sequence of events leading
   to failures.
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;em&gt;(Editor’s note: we decided against storing this meta-data information for various
   reasons.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Now the dev can do whatever he or she wishes in response to the exception.&amp;nbsp; Previously
   they might have written:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;try
   {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   ForEach(a, d);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}
   catch (FileNotFoundException fex) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // Handler(fex);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   And now they would have to instead write:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;try
   {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   ForAll(a, d);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}
   catch (AggregateException pex) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   List&amp;lt;Exception&amp;gt; unhandled = new List&amp;lt;Exception&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   foreach (Exception e in pex.InnerExceptions) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   FileNotFoundException fex = e as FileNotFoundException;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   if (fex == null) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   &amp;nbsp;&amp;nbsp;unhandled.Add(fex);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   } else {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // Handler(fex);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   }&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   }&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   if (unhandled.Count &amp;gt; 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   throw new AggregateException(unhandled);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   In other words, they would catch the AggregateException, enumerate over the inner
   exceptions, and react to any FileNotFoundExceptions as they would have normally.&amp;nbsp;
   (Taking into consideration that there might have been multiple.)&amp;nbsp; At the end,
   if there are any non-FileNotFoundExceptions left over, we propagate a new AggregateException
   with the handled FileNotFoundExceptions removed.&amp;nbsp; If there was only one remaining,
   we could, I suppose, try to rethrow just that, but this has the same nondeterminism
   problems mentioned above.
&lt;/p&gt;
&lt;p&gt;
   Very few people will write this code.&amp;nbsp; But one of the most vocal arguments against
   it is: just throw one singular exception, such as ForAllException, and let it crash,
   because no developer will handle it.&amp;nbsp; Well, that scheme is no better than throwing
   the AggregateException.&amp;nbsp; At least the aggregation model lets people write backout
   and recovery code if they have the patience to deal with the reality that multiple
   exceptions occurred.
&lt;/p&gt;
&lt;p&gt;
   To make this slightly easier, we could expose an API, ‘void Handle(Func&amp;lt;Exception,
   bool&amp;gt; a) where T : Exception’, that effectively encapsulates the same logic as
   shown above, repropagating the exception at the end if all the exceptions weren’t
   handled (i.e. some weren’t of type T):
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;try
   {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   ForAll(a, d);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}
   catch (AggregateException pex) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   pex.Handle(delegate(Exception ex) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   FileNotFoundException fex = ex as FileNotFoundException;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   if (fex != null) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // Handle(fex);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   return true;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   }&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   return false;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   });&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   (One problem with this approach is that the ‘throw’ inside of Handle will destroy
   the original stack trace for ‘pex’.&amp;nbsp; An alternative might be for Handle to modify
   the AggregateException in place, keeping the stack trace intact, returning a bool
   that the caller switches on and does a ‘throw’ if it returns false; this is unattractive
   because it’s error prone and could lead to accidentally swallowing, but in the end
   might help debuggability.)
&lt;/p&gt;
&lt;p&gt;
   If we cared about eliminating unnecessary catch/rethrows, we could use 1st pass filters
   instead, but this would only be available to VB and C++/CLI programmers, as C# doesn’t
   expose filters.&amp;nbsp; For example, in pseudo-code:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;try
   {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   ForAll(a, d);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}
   catch (fex.InnerExceptions.Contains&amp;lt;FileNotFoundException&amp;gt;()) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   // Handle …&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Although interesting, we’re trying to move away from our two pass model.&amp;nbsp; So
   let’s forget about this for now.
&lt;/p&gt;
&lt;p&gt;
   This approach suffers when composing with non-aggregate exception aware code.&amp;nbsp;
   For it to work well, everybody on the call stack needs to be looking inside the aggregate
   for “their” exception, handling it, and possibly repropagating.&amp;nbsp; If we want existing
   BCL APIs to start using data parallelism internally, we would have to be careful here,
   not to break AppCompat because we start throwing AggregateExceptions instead of the
   originals. 
&lt;/p&gt;
&lt;p&gt;
   This is probably where there’s an opportunity for better CLR and tool integration.&amp;nbsp;
   For instance, you could imagine a world where the CLR automatically unravels the parallel
   failures, matching and running handlers for specific exceptions inside the aggregate
   as it goes, but repropagating if all exceptions weren’t handled.&amp;nbsp; This is very
   hand-wavy and fundamentally changes the way exceptions work, so it would require a
   lot more thought.&amp;nbsp; A catch block that swallows an exception (today) is just about
   guaranteed—asynchronous exceptions aside—that the IP will soon reach the next instruction
   after the try/catch block.&amp;nbsp; This is a pretty basic invariant.&amp;nbsp; With this
   proposal, that wouldn’t be the case, and would be bound to break large swaths of code.&amp;nbsp;
   Sticking with the library approach (with all its imperfections) seems like the best
   plan of attack for now.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;Waiting for the “join” to finish&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   There was something implicit in the design mentioned above.&amp;nbsp; The ForAll API,
   and others like it, wouldn’t actually propagate exceptions until the fate of all threads
   was known.
&lt;/p&gt;
&lt;p&gt;
   Imagine we have the scenario described earlier (2048 elements, 8 threads), but slightly
   different: the 0th element causes an exception, but no other.&amp;nbsp; It turns out this
   is probably a common case, i.e. that only a subset of the partitions will yield an
   exception.&amp;nbsp; In this case, we would still have to wait for 7*256 = 1,792 elements
   to be run through ‘a’ before this exception is propagated.&amp;nbsp; Imagine a slightly
   different case.&amp;nbsp; The 0th element throws a catastrophic exception, and the application
   is going to terminate as soon as it propagates.&amp;nbsp; ‘a’ simply can’t be run any
   more, and will keep reporting back this same exception.&amp;nbsp; But it will take 8 of
   these exceptions to actually stop the application, i.e. by calling ‘a’ on the 0th,
   256th, 512th, etc. elements, if we wait for all tasks to complete.&amp;nbsp; If each exception
   corresponds to some failed attempt at forward progress, one that possibly corrupts
   state, then the damage is O(N) times “worse” (for some measurement) than in the sequential
   program, where N is the number of concurrent tasks.
&lt;/p&gt;
&lt;p&gt;
   Instead of waiting helplessly, we could try to aggressively shut down these concurrent
   workers.
&lt;/p&gt;
&lt;p&gt;
   At first, you might be tempted to employ CLR asynchronous thread aborts, but this
   is fraught with peril.&amp;nbsp; Almost all .NET Framework code today is taught that thread
   abort == AppDomain unload, and reacts accordingly.&amp;nbsp; State corruption stemming
   from libraries as fundamental as the BCL would be just about guaranteed.&amp;nbsp; Changing
   this state of mind and the state of our software would be quite the undertaking.
&lt;/p&gt;
&lt;p&gt;
   Instead, we can have the concurrent API itself periodically check an ‘abort’ flag
   shared among all workers.&amp;nbsp; The first thread to propagate an exception would set
   this flag.&amp;nbsp; And whenever a worker has seen that it has been set, it voluntarily
   returns instead of finishing processing data:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;for
   (int i = start_idx; i &amp;lt; end_idx &amp;amp;&amp;amp; !aborted; i++) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   a(d[i]);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; COLOR: #0f243e; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   This increases the responsiveness of exception propagation, but clearly isn’t foolproof.&amp;nbsp;
   There will still be a delay for long-running callbacks.&amp;nbsp; Thankfully, with PLINQ,
   TPL, and I hope most of our parallel libraries, the units of work will be individually
   fine-grained, and therefore this technique should suffice.
&lt;/p&gt;
&lt;p&gt;
   If a concurrent worker is blocked, there’s not a whole lot we can do.&amp;nbsp; Much like
   thread aborts, you might be tempted to use Thread.Interrupt to remove it from the
   wait condition.&amp;nbsp; Unfortunately this will leave state corruption in its wake,
   because plenty of code does things like WaitHandle.WaitOne(Timeout.Infinite) without
   checking the return value or expecting a ThreadInterruptionException.&amp;nbsp; The same
   argument applies to, say, user-mode APCs.&amp;nbsp; Eventually you might also be tempted
   to use IO cancellation in Windows Vista to cancel errant, runaway network or disk
   IO requests.&amp;nbsp; This would be great.&amp;nbsp; But this also generally has the same
   problem as interruption, so until we find a general solution to that, we can’t do
   any of this.
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;em&gt;(Editor’s note: We eventually solved this problem by coming up with a &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/06/22/9791840.aspx"&gt;unified
   cancellation framework&lt;/a&gt;.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   &lt;strong&gt;One last note&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
   This path forward seems best for now, but it leaves me wanting more.
&lt;/p&gt;
&lt;p&gt;
   In the end, this feels like a more fundamental problem.&amp;nbsp; An API like ForAll gives
   the illusion of an ordinary, old sequential caller/callee relationship.&amp;nbsp; But
   the callee doesn’t use a stack-based calling approach: instead, it distributes work
   among many concurrent workers, turning the linear stack into a sort of dynamically
   unfolding cactus stack (or tree).&amp;nbsp; And SEH exceptions are fundamentally linear
   stack-based creatures.
&lt;/p&gt;
&lt;p&gt;
   In this world, it’s just a simple fact that data all over the place can become corrupt
   simultaneously.&amp;nbsp; Many things can fail at once because many things are happening
   at once.&amp;nbsp; It’s inescapable.&amp;nbsp; Recovery is disastrously difficult, so most
   failures will end in crashes.&amp;nbsp; STM’s promise for automatic recovery offers a
   glimmer of hope, but without it, I worry that papering a sequential “feel” on top
   of data/task parallelism is a dangerous game to play.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=652962f1-5073-49a4-b233-9ca24b494742" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,652962f1-5073-49a4-b233-9ca24b494742.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=3a811f34-67a9-477f-b408-15a0d008caaf</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,3a811f34-67a9-477f-b408-15a0d008caaf.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,3a811f34-67a9-477f-b408-15a0d008caaf.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=3a811f34-67a9-477f-b408-15a0d008caaf</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      One of my many focuses lately has been developing a memory ordering model for our
      project here at Microsoft.  There are four main questions to answer when defining
      such a model:
   </p>
        <ol>
          <li>
         What are the ordering guarantees for ordinary loads and stores? 
      </li>
          <li>
         What are the ordering guarantees for volatile loads and stores? 
      </li>
          <li>
         What kinds of explicit fences are allowed? 
      </li>
          <li>
         Where are fences used automatically, e.g. to preserve type safety and security?</li>
        </ol>
        <p>
      These tend to be the differentiation points for any model.  Everything else is
      mostly commodity.  Not that there is much else, mind you, but respecting data
      dependence, not speculating ahead such that exceptions occur that wouldn't have occurred
      in a sequential execution, and so forth are all must haves, for instance.  Most
      interesting permutations of answers for these questions have already been explored,
      and industry consensus is being reached, so it would be better to say I've been picking
      a model rather than defining one.
   </p>
        <p>
      What's interesting is that memory model designers are often colored by their favorite
      architecture du jour.  If somebody cares primarily about X86, they are apt to
      choose something very strong.  If somebody cares primarily about ARM, however,
      they are apt to choose something very weak.  There is a classic tradeoff here. 
      Stronger means easier to program, while weaker means better performance.  For
      some reason, many of the projects I've worked on have had an abundance of strong hardware
      (like X86) and a scarcity of weak hardware (like ARM and IA64).  The reality
      sinks in: most developers on the team code to X86, and then when it comes time to
      getting more serious about the other platforms, code starts breaking all over the
      place.  This is why the CLR went so strong in 2.0, even though IA64 was
      an important platform to support.
   </p>
        <p>
      Let's look at some common answers to the above questions.
   </p>
        <p>
      For #1:
   </p>
        <ul>
          <li>
         C++, Visual C++, ECMA 1.0, Java Memory Model, and Prism: no ordering guarantees. 
      </li>
          <li>
         CLR 2.0: ordered stores, no ordering for loads.</li>
        </ul>
        <p>
      For #2:
   </p>
        <ul>
          <li>
         C++: prevents compiler-only code motion, but explicit fences are needed for processor
         ordering. 
      </li>
          <li>
         Visual C++, ECMA 1.0, and CLR 2.0: loads are acquire, stores are release ordered. 
      </li>
          <li>
         Java Memory Model: loads and stores are fully ordered (sequentially consistent).</li>
        </ul>
        <p>
      For #3:
   </p>
        <ul>
          <li>
         C++: implementation-specific. 
      </li>
          <li>
         Visual C++: intrinsics and Win32 APIs. 
      </li>
          <li>
         ECMA 1.0 and CLR 2.0: locks, and mostly Win32-style interlocked APIs. 
      </li>
          <li>
         Java Memory Model: locks, compare-and-swap, atomics, etc.</li>
        </ul>
        <p>
      For #4:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
      Managed environments like the CLR and JVM need to ensure type safety, even if ordinary
      loads and stores are unordered.  This is nontrivial, because the boundary around
      type safety is blurred.  Certainly we must ensure garbage v-table pointers are
      not seen.  But is a thread allowed to read non-zeroed memory behind an object
      reference?  And can it contain garbage (e.g. "values out of thin air")? 
      What about writes done by mutator threads, including write barriers, while a concurrent
      collector is tracing objects in the heap?  Are array lengths part of the set
      of protected fields that mustn't be read out of order?  Strings, since they are
      commonly used for security checking?  And so on.
   </p>
        </blockquote>
        <p>
      It is mainly the deep questions around #4, and also some simple compatibility struggles
      (around things like double checked locking), that caused the stronger answers for
      #1 in the CLR 2.0.
   </p>
        <p>
      In any case, I'm advocating a very different approach than the traditional models.
   </p>
        <p>
      We pick completely weak ordering for ordinary loads and stores, to enable efficient
      execution on weaker platforms like ARM, PowerPC, IA64, etc.  That part isn't
      new.  But here's the clincher.  <u>No volatiles</u>.  There <em>are</em> special
      variables that are used to communicate between threads (call them volatile if
      you'd like), but using them implies no kind of special automatic fencing.  Instead,
      whenever accessing such a variable, at the site of usage, the kind of fence desired <em>must</em> be
      used (compiler-enforced): full-fence (sequentially consistent), acquire-fence, release-fence,
      no-fence, or compiler-only-fence (for things like ensuring loads don't get hoisted
      as loop invariant).  Of course, certain kinds of fences are sprinkled throughout
      the system to guarantee type safety in all of the aforementioned places (and more),
      but these are implementation details.
   </p>
        <p>
      (This approach is rather like Herb Sutter's Prism and C++0x atomics.  See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm</a>.)
   </p>
        <p>
      Particularly after managing teams who developed a plethora of lock free code, I love
      this approach.  I can review code and immediately understand what ordering invariants
      the developer assumed when writing the code.  This doesn't really make writing
      lock free code any simpler, except that it forces you to pause and think about things
      a bit more carefully than you may have otherwise.  But it certainly makes code
      easier to understand and maintain, and makes it clear to people that sprinkling
      volatile all over the place isn't going to save your butt: the only thing that will
      do that is careful thinking and engineering. 
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=3a811f34-67a9-477f-b408-15a0d008caaf" />
      </body>
      <title>Exploring memory models</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,3a811f34-67a9-477f-b408-15a0d008caaf.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/06/17/ExploringMemoryModels.aspx</link>
      <pubDate>Wed, 17 Jun 2009 06:53:26 GMT</pubDate>
      <description>&lt;p&gt;
   One of my many focuses lately has been developing a memory ordering model for our
   project here at Microsoft.&amp;nbsp; There are four main questions to answer when defining
   such a model:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      What are the ordering guarantees for ordinary loads and stores? 
   &lt;li&gt;
      What are the ordering guarantees for volatile loads and stores? 
   &lt;li&gt;
      What kinds of explicit fences are allowed? 
   &lt;li&gt;
      Where are fences used automatically, e.g. to preserve type safety and security?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   These tend to be the differentiation points for any model.&amp;nbsp; Everything else is
   mostly commodity.&amp;nbsp; Not that there is much else, mind you, but respecting data
   dependence, not speculating ahead such that exceptions occur that wouldn't have occurred
   in a sequential execution, and so forth are all must haves, for instance.&amp;nbsp; Most
   interesting permutations of answers for these questions have already been explored,
   and industry consensus is being reached, so it would be better to say I've been picking
   a model rather than defining one.
&lt;/p&gt;
&lt;p&gt;
   What's interesting is that memory model designers are often colored by their favorite
   architecture du jour.&amp;nbsp; If somebody cares primarily about X86, they are apt to
   choose something very strong.&amp;nbsp; If somebody cares primarily about ARM, however,
   they are apt to choose something very weak.&amp;nbsp; There is a classic tradeoff here.&amp;nbsp;
   Stronger means easier to program, while weaker means better performance.&amp;nbsp; For
   some reason, many of the projects I've worked on have had an abundance of strong hardware
   (like X86) and a scarcity of weak hardware (like ARM and IA64).&amp;nbsp; The reality
   sinks in: most developers on the team code to X86, and then when it comes time to
   getting more serious about the other platforms, code starts breaking all over the
   place.&amp;nbsp; This is why the CLR went so strong in 2.0, even&amp;nbsp;though IA64 was
   an important platform to support.
&lt;/p&gt;
&lt;p&gt;
   Let's look at some common answers to the above questions.
&lt;/p&gt;
&lt;p&gt;
   For #1:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      C++, Visual C++, ECMA 1.0, Java Memory Model, and Prism: no ordering guarantees. 
   &lt;li&gt;
      CLR 2.0: ordered stores, no ordering for loads.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   For #2:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      C++: prevents compiler-only code motion, but explicit fences are needed for processor
      ordering. 
   &lt;li&gt;
      Visual C++, ECMA 1.0, and&amp;nbsp;CLR 2.0: loads are acquire, stores are release ordered. 
   &lt;li&gt;
      Java Memory Model: loads and stores are fully ordered (sequentially consistent).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   For #3:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      C++: implementation-specific. 
   &lt;li&gt;
      Visual C++: intrinsics and Win32 APIs. 
   &lt;li&gt;
      ECMA 1.0 and CLR 2.0: locks, and mostly Win32-style interlocked APIs. 
   &lt;li&gt;
      Java Memory Model: locks, compare-and-swap, atomics, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   For #4:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   Managed environments like the CLR and JVM need to ensure type safety, even if ordinary
   loads and stores are unordered.&amp;nbsp; This is nontrivial, because the boundary around
   type safety is blurred.&amp;nbsp; Certainly we must ensure garbage v-table pointers are
   not seen.&amp;nbsp; But is a thread allowed to read non-zeroed memory behind an object
   reference?&amp;nbsp; And can it contain garbage (e.g. "values out of thin air")?&amp;nbsp;
   What about writes done by mutator threads, including write barriers, while a concurrent
   collector is tracing objects in the heap?&amp;nbsp; Are array lengths part of the set
   of protected fields that mustn't be read out of order?&amp;nbsp; Strings, since they are
   commonly used for security checking?&amp;nbsp; And so on.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   It is mainly the deep questions around #4, and also some simple compatibility struggles
   (around things like double checked locking), that caused the stronger answers for
   #1 in the CLR 2.0.
&lt;/p&gt;
&lt;p&gt;
   In any case, I'm advocating a very different approach than the traditional models.
&lt;/p&gt;
&lt;p&gt;
   We pick completely weak ordering&amp;nbsp;for ordinary loads and stores, to enable efficient
   execution on weaker platforms like ARM, PowerPC, IA64, etc.&amp;nbsp; That part isn't
   new.&amp;nbsp; But here's the clincher.&amp;nbsp; &lt;u&gt;No volatiles&lt;/u&gt;.&amp;nbsp; There &lt;em&gt;are&lt;/em&gt; special
   variables&amp;nbsp;that are used to communicate between threads (call them volatile if
   you'd like), but using them implies no kind of special automatic fencing.&amp;nbsp; Instead,
   whenever accessing such a variable, at the site of usage, the kind of fence desired &lt;em&gt;must&lt;/em&gt; be
   used (compiler-enforced): full-fence (sequentially consistent), acquire-fence, release-fence,
   no-fence, or compiler-only-fence (for things like ensuring loads don't get hoisted
   as loop invariant).&amp;nbsp; Of course, certain kinds of fences are sprinkled throughout
   the system to guarantee type safety in all of the aforementioned places (and more),
   but these are implementation details.
&lt;/p&gt;
&lt;p&gt;
   (This approach is rather like Herb Sutter's Prism and C++0x atomics.&amp;nbsp; See &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm"&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm&lt;/a&gt;.)
&lt;/p&gt;
&lt;p&gt;
   Particularly after managing teams who developed a plethora of lock free code, I love
   this approach.&amp;nbsp; I can review code and immediately understand what ordering invariants
   the developer assumed when writing the code.&amp;nbsp; This doesn't really make writing
   lock free code any simpler, except that it forces you to pause and think about things
   a bit more carefully than you may have otherwise.&amp;nbsp; But it certainly makes code
   easier to understand and maintain, and makes it clear to people&amp;nbsp;that sprinkling
   volatile all over the place isn't going to save your butt: the only thing that will
   do that is careful thinking and engineering. 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=3a811f34-67a9-477f-b408-15a0d008caaf" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,3a811f34-67a9-477f-b408-15a0d008caaf.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=45fe761f-2f83-4b87-8f99-aee2a1b40b8c</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,45fe761f-2f83-4b87-8f99-aee2a1b40b8c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,45fe761f-2f83-4b87-8f99-aee2a1b40b8c.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=45fe761f-2f83-4b87-8f99-aee2a1b40b8c</wfw:commentRss>
      <slash:comments>12</slash:comments>
      <title>A scalable reader/writer scheme with optimistic retry</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,45fe761f-2f83-4b87-8f99-aee2a1b40b8c.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/06/05/AScalableReaderwriterSchemeWithOptimisticRetry.aspx</link>
      <pubDate>Fri, 05 Jun 2009 00:36:23 GMT</pubDate>
      <description>&lt;p&gt;
   An interesting alternative to reader/writer locks is to combine pessimistic writing
   with optimistic reading.&amp;nbsp; This borrows some ideas from transactional memory,
   although of course the ideas have existed long before.&amp;nbsp; I was reminded of this
   trick by a colleague on my new team just a couple days ago.
&lt;/p&gt;
&lt;p&gt;
   The basic idea is to read a bunch of state optimistically, without taking a lock of
   any sort, and then prior to using it for meaningful work (which may depend on the
   state being consistent and correct), a validation step must take place.&amp;nbsp; This
   validation uses version numbers which writers are responsible for maintaining.&amp;nbsp;
   Specifically, we'll use two version counters, version1 and version2: the writer increments
   version1, performs the writes, and then increments version2; and the reader reads
   version2, performs its reads, and then verifies that version 1 is equal to the version2
   that it saw at the start.&amp;nbsp; If this verification fails, we'll ordinarily just
   do a little spinning and then go back around the loop again.
&lt;/p&gt;
&lt;p&gt;
   Stop for a moment and ponder something very critical to this algorithm.&amp;nbsp; The
   writer increments variables in the opposite order of the reader's reads.&amp;nbsp; To
   see why this works, imagine we start with version1 == version2 == 0.&amp;nbsp; There are
   two hazards to worry about.&amp;nbsp; (1) A reader begins reading, and writes occur before
   it has finished.&amp;nbsp; And (2) a reader begins reading while a write is in progress.&amp;nbsp;
   These are simple to detect, and in fact boil down to the same thing.&amp;nbsp; A reader
   sees version2 == 0, and the first thing a writer does is version1++.&amp;nbsp; So when
   the reader attempts to validate, it will notice the version2 it saw != version1 any
   longer.&amp;nbsp; If the writer has already begun by the time the reader arrives, it is
   possible for the reader to know it is doomed even before it has started doing any
   of its reads.
&lt;/p&gt;
&lt;p&gt;
   Here is the code in its full glory:
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;using
   System;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;using
   System.Threading;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;public
   class OptimisticSynchronizer 
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;{&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;private
   volatile int m_version1;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;private
   volatile int m_version2;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   void BeforeWrite() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;++m_version1;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   void AfterWrite() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;++m_version2;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   ReadMark GetReadMark() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return
   new ReadMark(this, m_version2);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   struct ReadMark&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;private
   OptimisticSynchronizer m_sync;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;private
   int m_version;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;internal
   ReadMark(OptimisticSynchronizer sync, int version) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m_sync
   = sync;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m_version
   = version;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   bool IsValid {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;get
   { return m_sync.m_version1 == m_version; }&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   void DoWrite(Action writer) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;BeforeWrite();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try
   {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;writer();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}
   finally {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;AfterWrite();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   T DoRead&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; reader) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;T
   value = default(T);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;SpinWait
   sw = new SpinWait();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ReadMark
   mark = GetReadMark();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;value
   = reader();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (mark.IsValid) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;sw.SpinOnce();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return
   value;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
   We leave it to the caller of this class to acquire locks as appropriate to synchronize
   writers.&amp;nbsp; Typically this will just mean wrapping a Monitor.Enter/Exit around
   calls to things like BeforeWrite, AfterWrite, and DoWrite.&amp;nbsp; But readers explicitly
   do not need this same protection.&amp;nbsp; DoRead exemplifies the safe reading pattern,
   although it can be done by hand via the ReadMark APIs.
&lt;/p&gt;
&lt;p&gt;
   It's also worth considering what kinds of fences are truly required for this to work.&amp;nbsp;
   Logically speaking, we need to ensure the entrance to a protected block (either read
   or write) is an acquire fence, and exit from the block is a release fence.&amp;nbsp; This
   is similar to the ordering semenaitcs necessary for a lock block.&amp;nbsp; So long as
   we use volatile modifiers for the version counters, and for the variables read within
   the protected block, this will work fine.&amp;nbsp; Even on weak models like IA64.&amp;nbsp;
   The beautiful thing is that we don't need full fences, even on models like X86 that
   make use of store buffer forwarding&amp;nbsp; The&amp;nbsp;classic store buffering case we
   may worry about&amp;nbsp;(on a single-threaded execution)&amp;nbsp;would be something like
   this, in pseudo-code:
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;version1++;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;X
   = 42;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;Y
   = 99;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;version2++;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;tmp
   = version2;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;r0
   = X;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;r1
   = Y;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;success
   = (tmp == version1);&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;
   We'd be worried about satisfying some loads out of the store buffer, while satisfying
   others out of the memory system.&amp;nbsp; But this is safe: if the load of X or Y sees
   a different processor's writes, then the subsequent load of version1 necessarily must
   witness the new value written by the other processor too.&amp;nbsp; And therefore the
   validation will fail as we would expect and hope.
&lt;/p&gt;
&lt;p&gt;
   Here is a quick performance benchmark I whipped together, much in the same spirit
   as my previous reader/writer lock examples.&amp;nbsp; I've measured varying numbers of
   writers (0%, 5%, 10%, 25%, 50%, and 100%), and each thread spends a certain amount
   of time inside the "lock region" doing some nonsense busy work.&amp;nbsp; The certain
   amount of time is measured in terms of number of function calls (0, 10, 100, and 1000),
   and the work doesn't vary at all depending on whether a thread is reading or writing.&amp;nbsp;
   I've measured four things: (1) Monitor.Enter/Exit as the baseline (where both readers
   and writers just acquire the mutually exclusive lock), (2) ReaderWriterLockSlim, (3) &lt;a href="http://www.bluebytesoftware.com/blog/2009/02/21/AMoreScalableReaderwriterLockAndABitLessHarshConsiderationOfTheIdea.aspx"&gt;the
   spin-based lock that I showed previously&lt;/a&gt;, and (4) the new OptimisticSynchronizer
   class with optimistic retry.&amp;nbsp; The values are the ratio compared to the baseline
   (1), so that &amp;gt;1.0x means the particular entry is slower, while &amp;lt;1.0x is faster.&amp;nbsp;
   I did these measurements on an 8-way machine -- unlike &lt;a href="http://www.bluebytesoftware.com/blog/2009/02/21/AMoreScalableReaderwriterLockAndABitLessHarshConsiderationOfTheIdea.aspx"&gt;the
   previous study which was on a 4-way machine&lt;/a&gt; -- which means that 0.125x would be
   a linear speedup compared to the serialized Monitor version:
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;0%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.26&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.55&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.39&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.38&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.12&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.17&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.13&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.18&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.05&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.08&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.11&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.12&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;5%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.36&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.70&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.40&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.07&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.98&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.07&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.55&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.30&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.35&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.43&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.31&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.24&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;10%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.42&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.66&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.23&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.06&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.41&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.61&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.91&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.51&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.56&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.66&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.46&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.31&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;25%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.36&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.97&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.24&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.03&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;2.39&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;2.22&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.08&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.89&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.84&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.99&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.86&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.59&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;50%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.48&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.80&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.21&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.05&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;3.16&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;3.30&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.81&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.19&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.91&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.94&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.10&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.92&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
   &lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;100%
   writers:&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;10
   calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;100 calls&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1000
   calls&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;RWLSlim&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;1.35&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.67&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.22&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.09&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;SpinRWL&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;5.84&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;5.84&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;2.49&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.18&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;
   &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas; mso-bidi-font-family: Tahoma"&gt;&lt;font color=#000000&gt;OptSync&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/span&gt;0.93&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;0.99&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.13&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;1.17&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
   For all cases but the 100% writers case, the OptimisticSynchronizer class does extraordinarily
   well.
&lt;/p&gt;
&lt;p&gt;
   Although this approach screams performance-wise, it is admittedly much more difficult
   and error-prone&amp;nbsp;to use.&amp;nbsp; If the variables protected are references to heap
   objects, you need to worry about using the read protection each time you touch a field.&amp;nbsp;
   Just like locks, this technique doesn't compose.&amp;nbsp; As with anything other than
   simple locking, use this technique with great care and caution; although the built-in
   acquire and release fences shield you from memory model reordering issues, there are
   some easy traps you can fall into.&amp;nbsp; And as with any optimistic reading, memory
   safety is a necessity; trying to use these techniques in C++, for example, can easily
   lead to access violations and memory corruption.&amp;nbsp; Tread with caution.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;Update 6/4: &lt;/strong&gt;This technique, of course, is subject to ABA problems.&amp;nbsp;
   I failed to mention that originally.&amp;nbsp; That is, if between reading version2, Int32.MaxValue
   writers perform writes, the version1 field will wrap around such that the reader will
   (erroneously) successfully validate.&amp;nbsp; Fixing this on 64-bit is simple (use a
   64-bit counter) but is less so on 32-bit due to the lack of atomicity on loads and
   stores of 64-bit values (without using, say, an XCHG or related primitive).
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;Update 6/18: &lt;/strong&gt;My original write-up incorrectly made some hidden assumptions
   about the use of volatile.&amp;nbsp; This has now been cleared up.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=45fe761f-2f83-4b87-8f99-aee2a1b40b8c" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,45fe761f-2f83-4b87-8f99-aee2a1b40b8c.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <title>What Einstein's special theory of relativity can teach us about memory models</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/05/28/WhatEinsteinsSpecialTheoryOfRelativityCanTeachUsAboutMemoryModels.aspx</link>
      <pubDate>Thu, 28 May 2009 17:29:41 GMT</pubDate>
      <description>&lt;p&gt;
   Two persons stand on a railway embankment at points A and C, exactly 500 meters apart.
   Lightning strikes precisely in the center of them, at point B, 250 meters away from
   both:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;
   &lt;--A----------B----------C--&gt;
   &lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Presuming both persons are stationary, does the event (lightning strikes) occur “at
   the same time” from the perspective of the two persons? In our simplistic one dimensional
   model, the answer is Yes, precisely because the point of the lightning strike, B,
   is equidistant from A and C.
&lt;/p&gt;
&lt;p&gt;
   The person at point C may just as well be responsible for generating the event, by
   using some form of light rod instead of a lightning bolt supplied by nature. If the
   person at C lights such a rod, would the event still occur “at the same time” for
   both persons? Clearly No, because it will take some amount of time for the event’s
   occurrence to travel the distance from C to A, specifically the time it takes for
   light to travel 500 meters. Whereas for C it happens nearly instantaneously.
&lt;/p&gt;
&lt;p&gt;
   Practically speaking, this amount of time it takes for the light to travel to A will
   of course be so minute as to be nearly immeasurable, but nevertheless there are two
   separate times &lt;i&gt;t&lt;/i&gt; and &lt;i&gt;t’&lt;/i&gt;, the former being the actual time the rod is
   lit at C, and the latter being the time at which it is perceived at A. This is commonly
   referred to as relativity of simultaneity, introduced as Lorentz’s local time in the
   late 1800's and further formalized by Einstein's special theory in 1905.
&lt;/p&gt;
&lt;p&gt;
   Now imagine that a new person is placed at point B, equidistant from A and C, where
   the original lightning struck. If the person at C lights his rod, will the person
   at B observe the event before the person at A does? Most certainly. It takes less
   time for light to travel 250 meters than it does 500 meters.
&lt;/p&gt;
&lt;p&gt;
   Let us extend our working example a bit. Imagine again three persons, one at point
   A, one at point B, and another at point C. Those at B and C hold their own light rods.
   The person at C lights a rod, and in response to seeing C’s rod lighting, the person
   at B also lights a rod. The question is, must the person at A witness the light emanating
   from C’s rod prior to witnessing the light emanating from B’s rod? Unless the person
   at B’s response is truly instantaneous (which we assume is practically impossible),
   or unless he can see into the future (which we also assume is impossible), clearly
   the answer is Yes. Because the rod at B was lit in response to witnessing C’s lighting
   of the rod, some amount of time must have passed during the response, and the person
   at A will thus see C’s lighting first (or at the very least simultaneously, assuming
   near-impossible instantaneous response). We say B’s lighting is causally dependent
   on C’s lighting.
&lt;/p&gt;
&lt;p&gt;
   The main point here is that time is an illusion. There is no global time clock. Instead,
   events are not only distinguished by some monotonically increasing time value &lt;em&gt;t&lt;/em&gt;,
   but also by a location which is defined by three-space coordinates. This is Minkowski’s
   four-dimensional space. One event occurring at coordinates { x=0, y=0, z=0, &lt;em&gt;t&lt;/em&gt;=99
   } may not appear to be simultaneous with some other event at coordinates { x=42, y=42,
   z=42, &lt;em&gt;t&lt;/em&gt;=99 }, depending on the observer's location, even though both events
   occur at time &lt;em&gt;t&lt;/em&gt; = 99.
&lt;/p&gt;
&lt;p&gt;
   Perception is relative. There is no global total ordering, only a local (relative)
   one.
&lt;/p&gt;
&lt;p&gt;
   A similar phenomenon is true of multiprocessors. In fact, nearly everything said above
   applies equally to them, provided that you replace “persons” with “processors”, and
   lighting of rods with writes to memory and witnessing of the light with reads from
   memory.
&lt;/p&gt;
&lt;p&gt;
   Multiprocessor architects must cope with the increasing bottleneck on a central memory
   unit, particularly due to shared memory programming. One common means of doing so
   is to increase the distance between processing elements and the memory units they
   use, padding this distance with ample levels of cache. Some processor A may have a
   local memory (cache) that is separate from some other processor C’s, and A’s writes
   to it will be visible to A before C, for example. And if some processor B sits in
   between them, it may notice such writes before C does. Locality matters.
&lt;/p&gt;
&lt;p&gt;
   Of course, memory ordering models are meant to eliminate such distances from the programmer’s
   mind, at least to some degree. They provide a set of rules governing the timing and
   ordering of events. But there is just no denying the laws of physics. My claim is
   that a proper ordering model ought to obey what can be derived from the special theory
   of relativity: no more, no less. That is, the fundamental laws of how events occur
   and are correlated in the real world should be mimicked. This means only two things,
   as far as I can tell:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      An event stream (writes) originating from a source must appear to happen in order.&lt;/li&gt;
   &lt;li&gt;
      Causality is respected, in that when C causes B, it is implied that A must see C followed
      by B.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   This turns out to be stronger than some models, but also weaker in some regards. Distance
   and latency are first class, embellished, and allowed. There is some cost to ensuring
   events leaving a locale do so in order, and that events arriving into a locale also
   do so in order. Given coarse enough locales, however, this cost ought to be amortized
   over the cost of inter-locale communication.
&lt;/p&gt;
&lt;p&gt;
   Notice that sequential consistency is explicitly discouraged. The ordinary store-followed-by-load
   ordering that I've written about many times is legal. Considering this phenomena in
   the context of light rods and relativity makes it clear why. Imagine that the persons
   at A and C light their rods simultaneously. If the person at A immediately, after
   lighting the rod, looks to the right to see if C has lit the rod, the answer will
   be No; and similarly, if the person at C immediately, after lighting the rod, looks
   to the left to see if A has lit the rod, the answer will also be No. Although the
   real reason has to do with gross details like store buffers and cache coherency, the
   elegant reason supported by the model is that it takes time for light to travel the
   distance between A and C.
&lt;/p&gt;
&lt;p&gt;
   I also want to point out that “memory ordering model” commonly refers to individual
   loads and stores, at a very low level, but just as well applies to a higher-level
   model such as might be found in an actor-oriented (message passing) programming language.
   People often believe memory ordering and interleaving goes away magically with message
   passing models. This is simply not true, even if instruction-level interleaving is
   eliminated. The granularity merely coarsens, but the problem still remains the same.
&lt;/p&gt;
&lt;p&gt;
   Despite the lack of sequential consistency, implementing such a model can pose challenges,
   due to restrictions on optimizations like pipelining and out of order execution. (Hey,
   at least we needn’t worry about processors moving about at different velocities, as
   in the more interesting parts of special relativity.) But I believe it is necessary.
   This price paid will be rewarded with a system that human beings can be taught to
   reason about as they do in the real world. Remember: I am not just talking about memory
   models in the traditional sense, where people are tempted to sweep the problem under
   the rug of "only super-developers doing lock-free programming need a model"; it matters
   for higher level concurrency orchestration patterns too. In the end, let us not forget:
   correctness and understandability trump performance optimizations for all but the
   most low-level systems developers, which make up less than 1% of the development population.
&lt;/p&gt;
&lt;p&gt;
   &lt;font size=1&gt;1. Relativity: The Special and General Theory. &lt;/font&gt;&lt;a href="http://en.wikisource.org/wiki/Relativity:_The_Special_and_General_Theory"&gt;&lt;font size=1&gt;http://en.wikisource.org/wiki/Relativity:_The_Special_and_General_Theory&lt;/font&gt;&lt;/a&gt;
   &lt;br&gt;
   &lt;font size=1&gt;2. Time, Clocks, and the Ordering of Events in a Distributed System. &lt;/font&gt;&lt;a href="http://research.microsoft.com/en-us/um/people/lamport/pubs/time-clocks.pdf"&gt;&lt;font size=1&gt;http://research.microsoft.com/en-us/um/people/lamport/pubs/time-clocks.pdf&lt;/font&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,8ec6f1cf-bd9f-4776-8003-0c86eeee5b6e.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=4d4f41e3-0fca-400a-9829-941051d294fa</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,4d4f41e3-0fca-400a-9829-941051d294fa.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,4d4f41e3-0fca-400a-9829-941051d294fa.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=4d4f41e3-0fca-400a-9829-941051d294fa</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      A while back, <a href="http://www.bluebytesoftware.com/blog/2008/07/17/LoadsCannotPassOtherLoadsIsAMyth.aspx">I
      made a big stink</a> about what appeared to be the presence of illegal load-load reorderings
      in Intel's IA32 memory model.  They specifically claim this is impossible in
      their documentation.  Well, last week I was chatting with a colleague, <a href="http://research.microsoft.com/en-us/people/sburckha/">Sebastian
      Burckhardt</a>, about this disturbing fact.  And it turned out he had recently
      written a paper that formalizes the CLR 2.0 memory model, and in fact treats this
      phenomenon with a great deal of rigor:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>Verifying Compiler Transformations for Concurrent Programs</strong>
            <br />
            <a href="http://research.microsoft.com/pubs/76524/tr-2008-171-latest-03-11-09.pdf">http://research.microsoft.com/pubs/76524/tr-2008-171-latest-03-11-09.pdf</a>
          </p>
        </blockquote>
        <p>
      To jog your memory, the problematic example is
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">X = 1;<br />
      r0 = X;<br />
      r1 = Y;</font>
          </p>
        </blockquote>
        <p>
      where both X and Y are shared memory locations, and r0 and r1 are processor registers. 
      According to Intel's IA32 memory model, two loads to different locations cannot reorder. 
      But it is completely possible for the load of X to be satisfied out of the store buffer,
      and for r1=Y to pass the store (thereby also passing the load r0=X).  This is
      a standard Dekker reordering, but the usual example consists of just { X = 1; r1 =
      Y }.
   </p>
        <p>
      The key to modeling this is to turn an adjacent store-load affecting the same location
      into a single instruction.  Therefore, the above becomes something like:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">r0 = 1;<br />
      X = r0;<br />
      r1 = Y;</font>
          </p>
        </blockquote>
        <p>
      Now it becomes entirely clear what has gone wrong.  I have yet to see a clear
      description of this phenomenon, but Sebastian's paper does a great job.
   </p>
        <p>
      During the discussion, Sebastian showed me another disturbing four processor example:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">P0        P1       
       P2        P3<br />
      ==        ==         ==        ==<br />
      X = 1;    r0 = X;    Y = 1;    s0 = X;<br />
                r1 = Y;        
           s1 = Y;</font>
          </p>
        </blockquote>
        <p>
      Is it possible, after all four processors complete, that { r0 == 1, r1 == 0 } and
      { s0 == 0, s1 == 1 }?  This seems ridiculous, given a memory model where loads
      cannot reorder.  It seems that no serializable execution should lead to this. 
      But let's look at one problematic interleaving.  First, we merge the instruction
      stream on P0 with P1, and also P2 with P3.  This effect could occur if these
      writes are in functions that end up running on the same processor, or running on a
      machine that shares functional units (like hyperthreading), hierarchies that share
      a cache, and so on.  We end up with:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">P0/P1     P2/P3<br />
      =====     =====<br />
      X = 1     Y = 1;<br />
      r0 = X;   s0 = X;<br />
      r1 = Y;   s1 = Y;</font>
          </p>
        </blockquote>
        <p>
      Now let's permute these with the new rule introduced above in mind:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">P0/P1     P2/P3<br />
      =====     =====<br />
      r0 = 1;   s0 = X;<br />
      r1 = Y;   s1 = 1;<br />
      X = r0;   Y = s1;</font>
          </p>
        </blockquote>
        <p>
      At this point, it should be obvious what the problematic reordering would be. 
      Let's continue merging these into a single execution order:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New">P0/P1/P2/P3<br />
      ===========<br />
      r0 = 1; // #1<br />
      r1 = Y; // #0<br />
      s0 = X; // #0<br />
      s1 = 1; // #1<br />
      X = r0; // #1<br />
      Y = r1; // #1</font>
          </p>
        </blockquote>
        <p>
      The outcome?  { r0 == 1, r1 == 0 } and { s0 == 0, s1 == 1 }.  Whoops.
   </p>
        <p>
      I have yet to observe this happening in practice, but models that permit store buffer
      forwarding are fundamentally vulnerable to this reordering.  The solution here
      is the same as with Dekker.  Marking the volatiles is insufficient: you need
      to insert full memory fences between the store-load adjacent pairs.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=4d4f41e3-0fca-400a-9829-941051d294fa" />
      </body>
      <title>Loads cannot pass other loads, revisited</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,4d4f41e3-0fca-400a-9829-941051d294fa.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/05/17/LoadsCannotPassOtherLoadsRevisited.aspx</link>
      <pubDate>Sun, 17 May 2009 05:31:07 GMT</pubDate>
      <description>&lt;p&gt;
   A while back, &lt;a href="http://www.bluebytesoftware.com/blog/2008/07/17/LoadsCannotPassOtherLoadsIsAMyth.aspx"&gt;I
   made a big stink&lt;/a&gt; about what appeared to be the presence of illegal load-load reorderings
   in Intel's IA32 memory model.&amp;nbsp; They specifically claim this is impossible in
   their documentation.&amp;nbsp; Well, last week I was chatting with a colleague, &lt;a href="http://research.microsoft.com/en-us/people/sburckha/"&gt;Sebastian
   Burckhardt&lt;/a&gt;, about this disturbing fact.&amp;nbsp; And it turned out he had recently
   written a paper that formalizes the CLR 2.0 memory model, and in fact treats this
   phenomenon with a great deal of rigor:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;strong&gt;Verifying Compiler Transformations for Concurrent Programs&lt;/strong&gt;
   &lt;br&gt;
   &lt;a href="http://research.microsoft.com/pubs/76524/tr-2008-171-latest-03-11-09.pdf"&gt;http://research.microsoft.com/pubs/76524/tr-2008-171-latest-03-11-09.pdf&lt;/a&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   To jog your memory, the problematic example is
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;X = 1;&lt;br&gt;
   r0 = X;&lt;br&gt;
   r1 = Y;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   where both X and Y are shared memory locations, and r0 and r1 are processor registers.&amp;nbsp;
   According to Intel's IA32 memory model, two loads to different locations cannot reorder.&amp;nbsp;
   But it is completely possible for the load of X to be satisfied out of the store buffer,
   and for r1=Y to pass the store (thereby also passing the load r0=X).&amp;nbsp; This is
   a standard Dekker reordering, but the usual example consists of just { X = 1; r1 =
   Y }.
&lt;/p&gt;
&lt;p&gt;
   The key to modeling this is to turn an adjacent store-load affecting the same location
   into a single instruction.&amp;nbsp; Therefore, the above becomes something like:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;r0 = 1;&lt;br&gt;
   X = r0;&lt;br&gt;
   r1 = Y;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Now it becomes entirely clear what has gone wrong.&amp;nbsp; I have yet to see a clear
   description of this phenomenon, but Sebastian's paper does a great job.
&lt;/p&gt;
&lt;p&gt;
   During the discussion, Sebastian showed me another disturbing four processor example:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;P0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;P1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   &amp;nbsp;P2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; P3&lt;br&gt;
   ==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;==&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;==&lt;br&gt;
   X = 1;&amp;nbsp;&amp;nbsp; &amp;nbsp;r0 = X;&amp;nbsp;&amp;nbsp;&amp;nbsp; Y = 1;&amp;nbsp; &amp;nbsp;&amp;nbsp;s0 = X;&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;r1 = Y;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s1 = Y;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Is it possible, after all four processors complete, that { r0 == 1, r1 == 0 } and
   { s0 == 0, s1 == 1 }?&amp;nbsp; This seems ridiculous, given a memory model where loads
   cannot reorder.&amp;nbsp; It seems that no serializable execution should lead to this.&amp;nbsp;
   But let's look at one problematic interleaving.&amp;nbsp; First, we merge the instruction
   stream on P0 with P1, and also P2 with P3.&amp;nbsp; This effect could occur if these
   writes are in functions that end up running on the same processor, or running on a
   machine that shares functional units (like hyperthreading), hierarchies that share
   a cache, and so on.&amp;nbsp; We end up with:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;P0/P1&amp;nbsp;&amp;nbsp; &amp;nbsp; P2/P3&lt;br&gt;
   =====&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=====&lt;br&gt;
   X = 1&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Y = 1;&lt;br&gt;
   r0 = X;&amp;nbsp; &amp;nbsp;s0 = X;&lt;br&gt;
   r1 = Y;&amp;nbsp; &amp;nbsp;s1 = Y;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Now let's permute these with the new rule introduced above in mind:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;P0/P1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; P2/P3&lt;br&gt;
   =====&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=====&lt;br&gt;
   r0 = 1;&amp;nbsp;&amp;nbsp; s0 = X;&lt;br&gt;
   r1 = Y;&amp;nbsp;&amp;nbsp; s1 = 1;&lt;br&gt;
   X = r0;&amp;nbsp;&amp;nbsp; Y = s1;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   At this point, it should be obvious what the problematic reordering would be.&amp;nbsp;
   Let's continue merging these into a single execution order:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New"&gt;P0/P1/P2/P3&lt;br&gt;
   ===========&lt;br&gt;
   r0 = 1; // #1&lt;br&gt;
   r1 = Y; // #0&lt;br&gt;
   s0 = X; // #0&lt;br&gt;
   s1 = 1; // #1&lt;br&gt;
   X = r0; // #1&lt;br&gt;
   Y = r1; // #1&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The outcome?&amp;nbsp; { r0 == 1, r1 == 0 } and { s0 == 0, s1 == 1 }.&amp;nbsp; Whoops.
&lt;/p&gt;
&lt;p&gt;
   I have yet to observe this happening in practice, but models that permit store buffer
   forwarding are fundamentally vulnerable to this reordering.&amp;nbsp; The solution here
   is the same as with Dekker.&amp;nbsp; Marking the volatiles is insufficient: you need
   to insert full memory fences between the store-load adjacent pairs.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=4d4f41e3-0fca-400a-9829-941051d294fa" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,4d4f41e3-0fca-400a-9829-941051d294fa.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=bb1ac4c5-a53f-4d37-b78b-dbefabc13a54</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,bb1ac4c5-a53f-4d37-b78b-dbefabc13a54.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,bb1ac4c5-a53f-4d37-b78b-dbefabc13a54.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=bb1ac4c5-a53f-4d37-b78b-dbefabc13a54</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      As we were hard at work creating PFX, we had a <a href="http://blogs.msdn.com/texblog">sister
      team</a> of <a href="http://www.danielmoth.com/Blog/index.htm">great</a><a href="http://blogs.msdn.com/hshafi">talent</a> working
      with us every step of the way.  Their job?  To do to Visual Studio 2010
      what PFX did to .NET 4.0, by substantially improving the development experience for
      parallel programming on Windows.  This includes both diagnostics &amp; debugging,
      as well as <a href="http://www.bluebytesoftware.com/blog/'http://channel9.msdn.com/pdc2008/TL19/">profiling</a>.
   </p>
        <p>
      Daniel Moth, the program manager for a lot of the IDE features, just wrote up a comprehensive
      blog post on the new tasks window:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>
              <a href="http://www.danielmoth.com/Blog/2009/05/parallel-tasks-new-visual-studio-2010.html">Parallel
      Tasks - new Visual Studio 2010 debugger window</a>
            </strong>
          </p>
        </blockquote>
        <p>
      The new window gives you a view into all of the tasks in your process, their statuses,
      and where they are running:
   </p>
        <p>
          <img src="http://www.danielmoth.com/Blog/menu_plus_tasks.png" width="600" border="0" />
        </p>
        <p>
      Because both TPL and PLINQ use tasks for execution, it supports both quite nicely. 
      And it has (consistent!) support for both .NET and C++ tasks.  The parallel stacks
      window is also an impressive new feature, and I'm guessing Daniel will also cover
      that in the coming weeks.  Keep your eyes peeled. If all goes well, you'll even
      get to try them out first-hand, once Beta1 is available.
   </p>
        <p>
      And if that weren't enough to entice you to visit his blog, check out this nasty machine
      that Daniel uses to run his kitchen appliances:
   </p>
        <p>
          <img src="http://www.danielmoth.com/Blog/128VirtualProcessors.png" width="600" />
        </p>
        <p>
      Oh, the insanity.  I am thinking Task Manager will need revising in Windows 8.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=bb1ac4c5-a53f-4d37-b78b-dbefabc13a54" />
      </body>
      <title>PFX support in Visual Studio</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,bb1ac4c5-a53f-4d37-b78b-dbefabc13a54.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/05/17/PFXSupportInVisualStudio.aspx</link>
      <pubDate>Sun, 17 May 2009 00:27:35 GMT</pubDate>
      <description>&lt;p&gt;
   As we were hard at work creating PFX, we had a &lt;a href="http://blogs.msdn.com/texblog"&gt;sister
   team&lt;/a&gt; of &lt;a href="http://www.danielmoth.com/Blog/index.htm"&gt;great&lt;/a&gt; &lt;a href="http://blogs.msdn.com/hshafi"&gt;talent&lt;/a&gt; working
   with us every step of the way.&amp;nbsp; Their job?&amp;nbsp; To do to Visual Studio 2010
   what PFX did to .NET 4.0, by substantially improving the development experience for
   parallel programming on Windows.&amp;nbsp; This includes both diagnostics &amp;amp; debugging,
   as well as &lt;a href="http://www.bluebytesoftware.com/blog/'http://channel9.msdn.com/pdc2008/TL19/"&gt;profiling&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
   Daniel Moth, the program manager for a lot of the IDE features, just wrote up a comprehensive
   blog post on the new tasks window:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;strong&gt;&lt;a href="http://www.danielmoth.com/Blog/2009/05/parallel-tasks-new-visual-studio-2010.html"&gt;Parallel
   Tasks - new Visual Studio 2010 debugger window&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The new window gives you a view into all of the tasks in your process, their statuses,
   and where they are running:
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.danielmoth.com/Blog/menu_plus_tasks.png" width=600 border=0&gt;
&lt;/p&gt;
&lt;p&gt;
   Because both TPL and PLINQ use tasks for execution, it supports both quite nicely.&amp;nbsp;
   And it has (consistent!) support for both .NET and C++ tasks.&amp;nbsp; The parallel stacks
   window is also an impressive new feature, and I'm guessing Daniel will also cover
   that in the coming weeks.&amp;nbsp; Keep your eyes peeled. If all goes well, you'll even
   get to try them out first-hand, once Beta1 is available.
&lt;/p&gt;
&lt;p&gt;
   And if that weren't enough to entice you to visit his blog, check out this nasty machine
   that Daniel uses to run his kitchen appliances:
&lt;/p&gt;
&lt;p&gt;
   &lt;img src="http://www.danielmoth.com/Blog/128VirtualProcessors.png" width=600&gt;
&lt;/p&gt;
&lt;p&gt;
   Oh, the insanity.&amp;nbsp; I am thinking Task Manager will need revising in Windows 8.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=bb1ac4c5-a53f-4d37-b78b-dbefabc13a54" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,bb1ac4c5-a53f-4d37-b78b-dbefabc13a54.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=2a762dec-4076-4617-b327-1a5f8dd7947d</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,2a762dec-4076-4617-b327-1a5f8dd7947d.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,2a762dec-4076-4617-b327-1a5f8dd7947d.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2a762dec-4076-4617-b327-1a5f8dd7947d</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      The parallel computing team just shipped an early release <a href="http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx">Axum </a>(fka
      Maestro), an <a href="http://portal.acm.org/citation.cfm?id=36162">actor</a> based
      programming language with message passing and strong isolation.
   </p>
        <p>
      I'm personally very excited to see what comes of Axum.  It's one step on the
      long road towards the <a href="http://www.bluebytesoftware.com/blog/2009/04/01/ARantOnAutomaticParallelism.aspx">vision
      of automatic parallelism</a>.  Although I can't claim credit for anything concrete,
      I was the chief designer of the fine grained isolation model Axum is built atop (something
      I call "Taming Side Effects" (TSE)).  It's a blend of functional programming
      with imperative programming enabled by using the concepts of Haskell's <a href="http://portal.acm.org/citation.cfm?id=158524">state
      monad</a> in a more familiar way.  I'll try to blog a bit more about it in coming
      weeks.  It turns out I've recently shifted my focus to a <a href="http://blogs.msdn.com/cbrumme/archive/2006/09/15/756709.aspx">new
      project</a> with the aim of applying these ideas very broadly for a whole new platform.
   </p>
        <p>
      Doing incubation work at Microsoft is tough work, because it takes a strong vision
      and drive to keep pushing forward.  You need to take stances that are unconventional,
      risky, and often just plain unpopular, and drive against all odds.  Usually you
      aren't going to make any money off the ideas for years at a time, so it also takes
      a supportive management team who is willing to give you creative freedom and cut you
      checks.  Most such efforts fail in a vaccuum.  But hats off to the team
      for pushing hard, and going out early to ask what developers think.  This is
      a huge milestone.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=2a762dec-4076-4617-b327-1a5f8dd7947d" />
      </body>
      <title>Announcing the Axum programming language</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,2a762dec-4076-4617-b327-1a5f8dd7947d.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/05/08/AnnouncingTheAxumProgrammingLanguage.aspx</link>
      <pubDate>Fri, 08 May 2009 19:05:04 GMT</pubDate>
      <description>&lt;p&gt;
   The parallel computing team just shipped an early release &lt;a href="http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx"&gt;Axum &lt;/a&gt;(fka
   Maestro), an &lt;a href="http://portal.acm.org/citation.cfm?id=36162"&gt;actor&lt;/a&gt; based
   programming language with message passing and strong isolation.
&lt;/p&gt;
&lt;p&gt;
   I'm personally very excited to see what comes of Axum.&amp;nbsp; It's one step on the
   long road towards the &lt;a href="http://www.bluebytesoftware.com/blog/2009/04/01/ARantOnAutomaticParallelism.aspx"&gt;vision
   of automatic parallelism&lt;/a&gt;.&amp;nbsp; Although I can't claim credit for anything concrete,
   I was the chief designer of the fine grained isolation model Axum is built atop (something
   I call "Taming Side Effects" (TSE)).&amp;nbsp; It's a blend of functional programming
   with imperative programming enabled by using the concepts of Haskell's &lt;a href="http://portal.acm.org/citation.cfm?id=158524"&gt;state
   monad&lt;/a&gt; in a more familiar way.&amp;nbsp; I'll try to blog a bit more about it in coming
   weeks.&amp;nbsp; It turns out I've recently shifted my focus to a &lt;a href="http://blogs.msdn.com/cbrumme/archive/2006/09/15/756709.aspx"&gt;new
   project&lt;/a&gt; with the aim of applying these ideas very broadly for a whole new platform.
&lt;/p&gt;
&lt;p&gt;
   Doing incubation work at Microsoft is tough work, because it takes a strong vision
   and drive to keep pushing forward.&amp;nbsp; You need to take stances that are unconventional,
   risky, and often just plain unpopular, and drive against all odds.&amp;nbsp; Usually you
   aren't going to make any money off the ideas for years at a time, so it also takes
   a supportive management team who is willing to give you creative freedom and cut you
   checks.&amp;nbsp; Most such efforts fail in a vaccuum.&amp;nbsp; But hats off to the team
   for pushing hard, and going out early to ask what developers think.&amp;nbsp; This is
   a huge milestone.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=2a762dec-4076-4617-b327-1a5f8dd7947d" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,2a762dec-4076-4617-b327-1a5f8dd7947d.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=462c82b8-9a1e-4352-9e95-313fac6aa2bd</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,462c82b8-9a1e-4352-9e95-313fac6aa2bd.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,462c82b8-9a1e-4352-9e95-313fac6aa2bd.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=462c82b8-9a1e-4352-9e95-313fac6aa2bd</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I often speak of the need to develop programming models whereby developers write code
      in the most natural way possible, and it just so happens to be inherently parallel. 
      I don’t believe the lion’s share of developers want to rearchitect and rewrite their
      code with parallelism at the forefront of their development process.  They don’t
      want to think about shipping memory over to the GPU and launching a highly-specialized
      data parallel kernel of computation, nor do they want to have to add locks and transactions
      everywhere to make things safe.  But I do, however, believe the lion’s share
      of developers wouldn’t mind if their code ran faster as hardware got faster (via more
      cores).
   </p>
        <p>
      (To be clear, there are certainly a lot of developers who will be happy to write specialized
      code if it means eking out every last bit of performance on their machine.  But
      that’s the minority.)
   </p>
        <p>
      This viewpoint tends to get a lot of skeptical looks from people who quickly point
      out that this has been tried countless times before, and always leads to failure. 
      They, of course, are referring back to the 80’s and early 90’s where “dusty deck”
      parallelization was all the rage, mostly in the realm of vectorization and HPC. 
      To be fair, there were some mild successes in getting floating point loops parallelized,
      but there’s no wonder these attempts had little longevity.  No touch solutions
      are always inadequate.  Trying to make a fundamentally non-secure program secure,
      by way of, say, virtualization, may work in some constrained circumstances. 
      But the right solution is to develop models and practices that lead to security-by-construction.
   </p>
        <p>
      Furthermore, languages were (and in most cases still <em>are</em>) lacking some major
      prerequisites for large-scale automatic parallelization:
   </p>
        <ol>
          <li>
         Safety.  Unless a compiler can reason about the determinism of a program when
         run in parallel, one cannot prove that its results will remain correct when parallelism
         is added.  Compilers are therefore limited to parallelizing highly-specialized
         recognized patterns, like loops comprised solely of floating point additions of two
         arrays indexed by the loop iteration.<br /></li>
          <li>
         Performance.  Rampantly parallelizing a huge program wherever possible is dangerous,
         will drain performance, and make power consumption skyrocket.  Dynamic techniques
         like workstealing and static techniques like nested data parallelism and profile guided
         feedback need to work together to inform these decisions.  Machine-wide resource
         management needs to know about the memory topology, machine load and policy, and make
         informed decisions based on them.  Although there has been a lot of disparate
         research in these areas over the years, they have only recently been coming together. 
         Certainly in the 80’s, they were in their infancy.<br /></li>
          <li>
         Declarative patterns.  Most of the prior art was done in FORTRAN, a standard
         imperative language riddled with loops, effects, and assignments.  Programs need
         to be written with as few dependencies as possible in order to expose large amounts
         of parallelism, and the von Neumann inspired languages fall short of this aim. 
         Data comprehensions allow set-at-a-time computations to be expressed in a higher-order
         way, and newer languages like Fortress have language semantics that permit parallel
         evaluation in many more areas, like argument evaluation.  And application models
         that encourage isolation and loose state coupling allow coarse partitioning.</li>
        </ol>
        <p>
      In addition to all of those three things, we must have realistic expectations. 
      Even if a program were fully safe to parallelize, as many Haskell kernels are, we
      would seldom see perfect scaling.  Buying a 128-core machine doesn’t necessarily
      give you a 128x speedup.  Why?  Because there are still portions of the
      code that will end up less parallel than other portions, and some parts may even
      continue to run sequentially.  There will always be I/O and waiting: these are <em>real</em> programs,
      after all, and real programs tend not to be 100% computation.  They need to do
      something useful with the real world.  Moreover, safety does not mean “dependence
      free.”  And data dependencies are ultimately what limit parallelism.
   </p>
        <p>
      My stated goal would therefore be that parallelism in programs is solely limited by
      data dependence.  Safety issues are handled by construction.  Performance
      is (mostly) handled by the system, although as with all things, there will be some
      amount of measurement, hints, and tuning necessary.  But hopefully a huge part
      of tuning performance will be seeking out needless dependencies, or finding new algorithms
      that have different dependence characteristics.  And with that, we can focus
      our energy on raising the level of abstraction and pushing more declarative patterns
      that are broadly useful.  Over time as more and more programs are written in
      this fashion, they become more and more naturally parallel.
   </p>
        <p>
      What do you think?  Am I crazy?  Perhaps.  But I still know we can
      do it.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=462c82b8-9a1e-4352-9e95-313fac6aa2bd" />
      </body>
      <title>A rant on automatic parallelism</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,462c82b8-9a1e-4352-9e95-313fac6aa2bd.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/04/01/ARantOnAutomaticParallelism.aspx</link>
      <pubDate>Wed, 01 Apr 2009 03:29:49 GMT</pubDate>
      <description>&lt;p&gt;
   I often speak of the need to develop programming models whereby developers write code
   in the most natural way possible, and it just so happens to be inherently parallel.&amp;nbsp;
   I don’t believe the lion’s share of developers want to rearchitect and rewrite their
   code with parallelism at the forefront of their development process.&amp;nbsp; They don’t
   want to think about shipping memory over to the GPU and launching a highly-specialized
   data parallel kernel of computation, nor do they want to have to add locks and transactions
   everywhere to make things safe.&amp;nbsp; But I do, however, believe the lion’s share
   of developers wouldn’t mind if their code ran faster as hardware got faster (via more
   cores).
&lt;/p&gt;
&lt;p&gt;
   (To be clear, there are certainly a lot of developers who will be happy to write specialized
   code if it means eking out every last bit of performance on their machine.&amp;nbsp; But
   that’s the minority.)
&lt;/p&gt;
&lt;p&gt;
   This viewpoint tends to get a lot of skeptical looks from people who quickly point
   out that this has been tried countless times before, and always leads to failure.&amp;nbsp;
   They, of course, are referring back to the 80’s and early 90’s where “dusty deck”
   parallelization was all the rage, mostly in the realm of vectorization and HPC.&amp;nbsp;
   To be fair, there were some mild successes in getting floating point loops parallelized,
   but there’s no wonder these attempts had little longevity.&amp;nbsp; No touch solutions
   are always inadequate.&amp;nbsp; Trying to make a fundamentally non-secure program secure,
   by way of, say, virtualization, may work in some constrained circumstances.&amp;nbsp;
   But the right solution is to develop models and practices that lead to security-by-construction.
&lt;/p&gt;
&lt;p&gt;
   Furthermore, languages were (and in most cases still &lt;em&gt;are&lt;/em&gt;) lacking some major
   prerequisites for large-scale automatic parallelization:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      Safety.&amp;nbsp; Unless a compiler can reason about the determinism of a program when
      run in parallel, one cannot prove that its results will remain correct when parallelism
      is added.&amp;nbsp; Compilers are therefore limited to parallelizing highly-specialized
      recognized patterns, like loops comprised solely of floating point additions of two
      arrays indexed by the loop iteration.&lt;br&gt;
   &lt;/li&gt;
   &lt;li&gt;
      Performance.&amp;nbsp; Rampantly parallelizing a huge program wherever possible is dangerous,
      will drain performance, and make power consumption skyrocket.&amp;nbsp; Dynamic techniques
      like workstealing and static techniques like nested data parallelism and profile guided
      feedback need to work together to inform these decisions.&amp;nbsp; Machine-wide resource
      management needs to know about the memory topology, machine load and policy, and make
      informed decisions based on them.&amp;nbsp; Although there has been a lot of disparate
      research in these areas over the years, they have only recently been coming together.&amp;nbsp;
      Certainly in the 80’s, they were in their infancy.&lt;br&gt;
   &lt;/li&gt;
   &lt;li&gt;
      Declarative patterns.&amp;nbsp; Most of the prior art was done in FORTRAN, a standard
      imperative language riddled with loops, effects, and assignments.&amp;nbsp; Programs need
      to be written with as few dependencies as possible in order to expose large amounts
      of parallelism, and the von Neumann inspired languages fall short of this aim.&amp;nbsp;
      Data comprehensions allow set-at-a-time computations to be expressed in a higher-order
      way, and newer languages like Fortress have language semantics that permit parallel
      evaluation in many more areas, like argument evaluation.&amp;nbsp; And application models
      that encourage isolation and loose state coupling allow coarse partitioning.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   In addition to all of those three things, we must have realistic expectations.&amp;nbsp;
   Even if a program were fully safe to parallelize, as many Haskell kernels are, we
   would seldom see perfect scaling.&amp;nbsp; Buying a 128-core machine doesn’t necessarily
   give you a 128x speedup.&amp;nbsp; Why?&amp;nbsp; Because there are still portions of the
   code that will end up less parallel than other portions, and some&amp;nbsp;parts may even
   continue to run sequentially.&amp;nbsp; There will always be I/O and waiting: these are &lt;em&gt;real&lt;/em&gt; programs,
   after all, and real programs tend not to be 100% computation.&amp;nbsp; They need to do
   something useful with the real world.&amp;nbsp; Moreover, safety does not mean “dependence
   free.”&amp;nbsp; And data dependencies are ultimately what limit parallelism.
&lt;/p&gt;
&lt;p&gt;
   My stated goal would therefore be that parallelism in programs is solely limited by
   data dependence.&amp;nbsp; Safety issues are handled by construction.&amp;nbsp; Performance
   is (mostly) handled by the system, although as with all things, there will be some
   amount of measurement, hints, and tuning necessary.&amp;nbsp; But hopefully a huge part
   of tuning performance will be seeking out needless dependencies, or finding new algorithms
   that have different dependence characteristics.&amp;nbsp; And with that, we can focus
   our energy on raising the level of abstraction and pushing more declarative patterns
   that are broadly useful.&amp;nbsp; Over time as more and more programs are written in
   this fashion, they become more and more naturally parallel.
&lt;/p&gt;
&lt;p&gt;
   What do you think?&amp;nbsp; Am I crazy?&amp;nbsp; Perhaps.&amp;nbsp; But I still know we can
   do it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=462c82b8-9a1e-4352-9e95-313fac6aa2bd" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,462c82b8-9a1e-4352-9e95-313fac6aa2bd.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=223970c3-e1cc-4b09-9d61-99e8c5fae470</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=223970c3-e1cc-4b09-9d61-99e8c5fae470</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Managed code generally is not hardened against asynchronous exceptions.
   </p>
        <p>
      “Hardened” simply means “written to preserve state invariants in the face of unexpected
      failure.”  In other words, hardened code can tolerate an exception and continue
      being called subsequently without a process or machine restart.  Conversely,
      code that is not hardened may react sporadically if continued use is attempted: by
      corrupting state and subsequently behaving strangely and unpredictably.
   </p>
        <p>
      Asynchronous exceptions are a foreign concept to native programmers, and arise because
      there is a runtime underneath all managed code that is silently injecting code on
      behalf of the original program.  The only truly asynchronous exception is ThreadAbortException,
      but any in the set { OutOfMemoryException, TypeInitializationException, ThreadInterruptedException,
      StackOverflowException } are often labeled as such.  While thread aborts can
      happen at any line of code outside a delay-abort regions, these other exceptions can
      be introduced by the CLR at surprising times; i.e., { memory allocations, static member
      access, blocking calls, any function call }.  The effect is that, unlike most
      exceptions, the points at which they may occur are not obvious.  OOMs, for instance,
      can happen at any method call (due to failure to allocate memory in which to JIT code),
      implicit boxing, etc.
   </p>
        <p>
      (As of 2.0, StackOverflowException is no longer relevant because SO triggers a FailFast
      of the process instead.  So saying that managed code is not hardened against
      SO is an understatement.)
   </p>
        <p>
      Also, because of the way COM reentrancy works, any blocking call can lead to any arbitrary
      code dispatched through STA pumping.  And that arbitrary code, much like an APC,
      can fail via any arbitrary exception.  These are a lot like asynchronous exceptions. 
      So in truth, code that isn’t written to respond to arbitrary exceptions at all blocking
      points is technically not hardened either.
   </p>
        <p>
      .NET doesn’t provide checked exceptions, so the blunt reality is that very little
      managed code is hardened properly to synchronous exceptions either.  I think
      we do a better job in the framework of carefully engineering the code to resiliently
      tolerate failure, usually by being very careful about argument validation, but we
      aren’t perfect.  Some things slip through.
   </p>
        <p>
      If you stop to think about why hardening isn’t done, it’s probably obvious. 
      It’s darn difficult.  Especially for asynchronous exceptions where nearly every
      line of code must be considered.  In Win32 programming, most failure points are
      indicated by return codes.  (Although C++ exceptions can sneak through the cracks
      at surprising times.  Like the fact that EnterCriticalSection can throw.) 
      While error codes are cumbersome to program against (since every call needs to be
      checked for a plethora of conditions, making it easy to miss something), at least
      the response to failure is explicit.  You can decide to propagate and leave state
      corrupt, fix up state and then propagate, rip the process, or ignore the failure,
      as appropriate.  This becomes part of the API contract.  In managed code,
      you need to know to wrap such calls in try/catch blocks.  Nobody does this. 
      It’s insane to even consider doing that.  And because nobody does, you can’t
      even catch exceptions coming out of a single API call and know that, when faced with
      an OOM (for example), that all code on the propagating callgraph has transitively
      handled the failure in a controlled manner.  The very fact that the lock{} statement
      auto-unlocks without rolling back corrupt state should be indication enough of the
      current state of affairs.
   </p>
        <p>
      An instance of any of the aforementioned exceptions means the AppDomain is toast.
   </p>
        <p>
      By toast, I mean that it’s soon going to be unusable, and hopefully actively being
      unloaded.  Code in the framework assumes this, and you should too.  All
      it does is try to get out of the way by not crashing or hanging the ensuing unload. 
      A small fraction of code that deals with process-wide state comprised of resources
      not under the purview of the CLR GC needs to worry about running and avoiding leaks. 
      This is where things like <a href="http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx">CERs</a>, <a href="http://www.bluebytesoftware.com/blog/2005/12/27/NeverWriteAFinalizerAgainWellAlmostNever.aspx">CriticalFinalizerObjects</a>,
      and <a href="http://www.bluebytesoftware.com/blog/2005/03/19/AtomicityAndAsynchronousExceptionFailures.aspx">paired
      operations stuck in finally blocks</a> come into play.  They ensure cross-process
      state is freed, and that asynchronous exceptions cannot occur in places that would
      crash or hang a clean unload.
   </p>
        <p>
      Unfortunately, it’s not always the case that the AppDomain is unloading when such
      an exception occurs:
   </p>
        <ul>
          <li>
         Somebody can call Thread.Abort directly, without killing the AppDomain.  They
         can either call ResetAbort and keep it around, or let it return to the ThreadPool
         which catches and swallows aborts.  In fact, we tell people that synchronous
         aborts a la Thread.CurrentThread.Abort is “always safe”, whereas we tell people asynchronous
         aborts are dangerous and best avoided. 
      </li>
          <li>
         Some framework infrastructure, most notably ASP.NET, even aborts individual threads
         routinely without unloading the domain.  They backstop the ThreadAbortExceptions,
         call ResetAbort on the thread and reuse it or return it to the CLR ThreadPool. 
         That means any code running in ASP.NET is apt to be corrupted when websites are recycled
         and AppDomain isolation is not being used. 
      </li>
          <li>
         Assume AppDomain B is being unloaded.  If some thread has called from A to B
         to C, the thread will immediately suffer an abort.  The result is that C will
         see a thread unwinding with a ThreadAbortException, back into B, and then back to
         A, at which point the exception turns into a deniable AppDomainUnloadedException that
         can be caught.  But C has seen an in-flight abort and yet it is not being unloaded. 
         The result is that C’s state may be completely corrupt.  I believe this should
         be considered a bug in the CLR. 
      </li>
          <li>
         We can’t differentiate between soft- and hard-OOMs today.  The former are caused
         by requests to allocate large blocks memory.  Often a failure here isn’t indicative
         of a disaster.  It may be due to a need to allocate 1GB of contiguous memory,
         and perhaps there is fragmentation.  Hard OOMs are often caused by running up
         against the edge of the machine where no pagefile space is available, and may indicate
         a failure to JIT some important method, among other things.  But because we don’t
         differentiate, any managed code can catch-and-ignore any kind of OOM, including hard
         ones. 
      </li>
          <li>
         Thread interruptions are often used as a form of inter-thread communication. 
         For example, they can be used as a poor man’s cancellation.  (This is inappropriate,
         and cooperative techniques should always be used.  But it is widespread.) 
         But because they are used as a means of communication, they are almost always caught
         and handled in some controlled manner.  This is one place where we screwed up
         by not hardening the frameworks against interrupted blocking calls and reacting intelligently. 
         Checked exceptions would have saved us.</li>
        </ul>
        <p>
      What does all of this mean?  Quite simply, the .NET Framework cannot be trusted
      when any of the aforementioned exceptions are thrown.  Ideally the process will
      come tumbling down shortly thereafter, but improperly written code can catch them
      and continue trying to limp along.  In fact, as I mentioned above, some wildly
      popular &amp; successful application models do (notably, ASP.NET and WinForms).
   </p>
        <p>
      This state of affairs is admittedly unfortunate.  We don’t properly separate
      out the truly fatal exceptions from those that we can gracefully recover from. 
      In an ideal world, I’d love to see us do that.  For example:
   </p>
        <ol>
          <li>
         At some point, we really ought to consider FailFast instead of continuing to run code
         under failures we know are fatal and dangerous to attempt to recover from, much like
         we do with SO.  At least these failures should be undeniable like thread aborts
         are.  But this is a fairly Byzantine response and is not for the faint of heart. 
         Given that we still live in a world where WinForms wraps the top-most frame of the
         GUI thread in a catch-all, presents a dialog box, and allows a user to click “Ignore
         &amp; Continue”, I seriously doubt we’ll get there anytime soon. 
      </li>
          <li>
         Never expose a ThreadAbortException to code in an AppDomain unless we can guarantee
         the AppDomain is being unloaded.  That means getting rid of the Abort API, and
         thus indirectly disallowing code from catching and calling ResetAbort.  It also
         means the A calls B calls C case would not allow B to unload until the thread voluntarily
         unwinds out of C. 
      </li>
          <li>
         Allow OOMs to be caught only when they are soft.  That means a call to ‘new’,
         and it means the catch much occur inside the same stack frame as the call to ‘new’. 
         Such exceptions can be tolerated if code is properly written, and we will tell developed
         to be mindful of them.  Once such an OOM propagates past the calling stack frame,
         they will escalate to hard. 
      </li>
          <li>
         All other OOMs are hard and fatal.  This includes failure to allocate memory
         to JIT code and failure to allocate 20 bytes to box an int.  Hard OOMs are thus
         undeniable. 
      </li>
          <li>
         Get rid of ThreadInterruptedExceptions.  We screwed this up from Day One, and
         it’s probably too late to fix this.  We added cooperative cancellation in .NET
         4.0 for a reason. 
      </li>
          <li>
         TypeInitializationExceptions can probably stay, but we should allow rerunning the
         cctor upon subsequent accesses.  Today, once a class C throws from its cctor,
         the class can never be constructed.  So on the current plan, it only makes sense
         to FailFast.</li>
        </ol>
        <p>
      I’m sure there are many other things we could do to improve things.  But these
      6 general themes would be a great start.
   </p>
        <p>
      I’m just spitballing here.  There are no concrete plans to do any of these
      6 things as far as I know.  And at the end of the day, hardening only improves
      the statistics of the situation, so it tends to be very difficult to argue for one
      change over another, particularly if taking the change would make existing programs
      break.  But I really would like to see the base level of reliability in managed
      code improve with time.  Especially with the exciting work going on around <a href="http://blogs.msdn.com/bclteam/archive/2009/02/23/preview-of-code-contract-tools-now-available-melitta-andersen.aspx">contract-checking
      in the BCL</a> in Visual Studio 10, I hope these topics become top-of-mind for
      folks again in the near future.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=223970c3-e1cc-4b09-9d61-99e8c5fae470" />
      </body>
      <title>Managed code and asynchronous exception hardening</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/03/13/ManagedCodeAndAsynchronousExceptionHardening.aspx</link>
      <pubDate>Fri, 13 Mar 2009 20:24:25 GMT</pubDate>
      <description>&lt;p&gt;
   Managed code generally is not hardened against asynchronous exceptions.
&lt;/p&gt;
&lt;p&gt;
   “Hardened” simply means “written to preserve state invariants in the face of unexpected
   failure.”&amp;nbsp; In other words, hardened code can tolerate an exception and continue
   being called subsequently without a process or machine restart.&amp;nbsp; Conversely,
   code that is not hardened may react sporadically if continued use is attempted: by
   corrupting state and subsequently&amp;nbsp;behaving strangely and unpredictably.
&lt;/p&gt;
&lt;p&gt;
   Asynchronous exceptions are a foreign concept to native programmers, and arise because
   there is a runtime underneath all managed code that is silently injecting code on
   behalf of the original program.&amp;nbsp; The only truly asynchronous exception is ThreadAbortException,
   but any in the set { OutOfMemoryException, TypeInitializationException, ThreadInterruptedException,
   StackOverflowException } are often labeled as such.&amp;nbsp; While thread aborts can
   happen at any line of code outside a delay-abort regions, these other exceptions can
   be introduced by the CLR at surprising times; i.e., { memory allocations, static member
   access, blocking calls, any function call }.&amp;nbsp; The effect is that, unlike most
   exceptions, the points at which they may occur are not obvious.&amp;nbsp; OOMs, for instance,
   can happen at any method call (due to failure to allocate memory in which to JIT code),
   implicit boxing, etc.
&lt;/p&gt;
&lt;p&gt;
   (As of 2.0, StackOverflowException is no longer relevant because SO triggers a FailFast
   of the process instead.&amp;nbsp; So saying that managed code is not hardened against
   SO is an understatement.)
&lt;/p&gt;
&lt;p&gt;
   Also, because of the way COM reentrancy works, any blocking call can lead to any arbitrary
   code dispatched through STA pumping.&amp;nbsp; And that arbitrary code, much like an APC,
   can fail via any arbitrary exception.&amp;nbsp; These are a lot like asynchronous exceptions.&amp;nbsp;
   So in truth, code that isn’t written to respond to arbitrary exceptions at all blocking
   points is technically not hardened either.
&lt;/p&gt;
&lt;p&gt;
   .NET doesn’t provide checked exceptions, so the blunt reality is that very little
   managed code is hardened properly to synchronous exceptions either.&amp;nbsp; I think
   we do a better job in the framework of carefully engineering the code to resiliently
   tolerate failure, usually by being very careful about argument validation, but we
   aren’t perfect.&amp;nbsp; Some things slip through.
&lt;/p&gt;
&lt;p&gt;
   If you stop to think about why hardening isn’t done, it’s probably obvious.&amp;nbsp;
   It’s darn difficult.&amp;nbsp; Especially for asynchronous exceptions where nearly every
   line of code must be considered.&amp;nbsp; In Win32 programming, most failure points are
   indicated by return codes.&amp;nbsp; (Although C++ exceptions can sneak through the cracks
   at surprising times.&amp;nbsp; Like the fact that EnterCriticalSection can throw.)&amp;nbsp;
   While error codes are cumbersome to program against (since every call needs to be
   checked for a plethora of conditions, making it easy to miss something), at least
   the response to failure is explicit.&amp;nbsp; You can decide to propagate and leave state
   corrupt, fix up state and then propagate, rip the process, or ignore the failure,
   as appropriate.&amp;nbsp; This becomes part of the API contract.&amp;nbsp; In managed code,
   you need to know to wrap such calls in try/catch blocks.&amp;nbsp; Nobody does this.&amp;nbsp;
   It’s insane to even consider doing that.&amp;nbsp; And because nobody does, you can’t
   even catch exceptions coming out of a single API call and know that, when faced with
   an OOM (for example), that all code on the propagating callgraph has transitively
   handled the failure in a controlled manner.&amp;nbsp; The very fact that the lock{} statement
   auto-unlocks without rolling back corrupt state should be indication enough of the
   current state of affairs.
&lt;/p&gt;
&lt;p&gt;
   An instance of any of the aforementioned exceptions means the AppDomain is toast.
&lt;/p&gt;
&lt;p&gt;
   By toast, I mean that it’s soon going to be unusable, and hopefully actively being
   unloaded.&amp;nbsp; Code in the framework assumes this, and you should too.&amp;nbsp; All
   it does is try to get out of the way by not crashing or hanging the ensuing unload.&amp;nbsp;
   A small fraction of code that deals with process-wide state comprised of resources
   not under the purview of the CLR GC needs to worry about running and avoiding leaks.&amp;nbsp;
   This is where things like &lt;a href="http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx"&gt;CERs&lt;/a&gt;, &lt;a href="http://www.bluebytesoftware.com/blog/2005/12/27/NeverWriteAFinalizerAgainWellAlmostNever.aspx"&gt;CriticalFinalizerObjects&lt;/a&gt;,
   and &lt;a href="http://www.bluebytesoftware.com/blog/2005/03/19/AtomicityAndAsynchronousExceptionFailures.aspx"&gt;paired
   operations stuck in finally blocks&lt;/a&gt; come into play.&amp;nbsp; They ensure cross-process
   state is freed, and that asynchronous exceptions cannot occur in places that would
   crash or hang a clean unload.
&lt;/p&gt;
&lt;p&gt;
   Unfortunately, it’s not always the case that the AppDomain is unloading when such
   an exception occurs:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      Somebody can call Thread.Abort directly, without killing the AppDomain.&amp;nbsp; They
      can either call ResetAbort and keep it around, or let it return to the ThreadPool
      which catches and swallows aborts.&amp;nbsp; In fact, we tell people that synchronous
      aborts a la Thread.CurrentThread.Abort is “always safe”, whereas we tell people asynchronous
      aborts are dangerous and best avoided. 
   &lt;li&gt;
      Some framework infrastructure, most notably ASP.NET, even aborts individual threads
      routinely without unloading the domain.&amp;nbsp; They backstop the ThreadAbortExceptions,
      call ResetAbort on the thread and reuse it or return it to the CLR ThreadPool.&amp;nbsp;
      That means any code running in ASP.NET is apt to be corrupted when websites are recycled
      and AppDomain isolation is not being used. 
   &lt;li&gt;
      Assume AppDomain B is being unloaded.&amp;nbsp; If some thread has called from A to B
      to C, the thread will immediately suffer an abort.&amp;nbsp; The result is that C will
      see a thread unwinding with a ThreadAbortException, back into B, and then back to
      A, at which point the exception turns into a deniable AppDomainUnloadedException that
      can be caught.&amp;nbsp; But C has seen an in-flight abort and yet it is not being unloaded.&amp;nbsp;
      The result is that C’s state may be completely corrupt.&amp;nbsp; I believe this should
      be considered a bug in the CLR. 
   &lt;li&gt;
      We can’t differentiate between soft- and hard-OOMs today.&amp;nbsp; The former are caused
      by requests to allocate large blocks memory.&amp;nbsp; Often a failure here isn’t indicative
      of a disaster.&amp;nbsp; It may be due to a need to allocate 1GB of contiguous memory,
      and perhaps there is fragmentation.&amp;nbsp; Hard OOMs are often caused by running up
      against the edge of the machine where no pagefile space is available, and may indicate
      a failure to JIT some important method, among other things.&amp;nbsp; But because we don’t
      differentiate, any managed code can catch-and-ignore any kind of OOM, including hard
      ones. 
   &lt;li&gt;
      Thread interruptions are often used as a form of inter-thread communication.&amp;nbsp;
      For example, they can be used as a poor man’s cancellation.&amp;nbsp; (This is inappropriate,
      and cooperative techniques should always be used.&amp;nbsp; But it is widespread.)&amp;nbsp;
      But because they are used as a means of communication, they are almost always caught
      and handled in some controlled manner.&amp;nbsp; This is one place where we screwed up
      by not hardening the frameworks against interrupted blocking calls and reacting intelligently.&amp;nbsp;
      Checked exceptions would have saved us.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   What does all of this mean?&amp;nbsp; Quite simply, the .NET Framework cannot be trusted
   when any of the aforementioned exceptions are thrown.&amp;nbsp; Ideally the process will
   come tumbling down shortly thereafter, but improperly written code can catch them
   and continue trying to limp along.&amp;nbsp; In fact, as I mentioned above, some wildly
   popular &amp;amp; successful application models do (notably, ASP.NET and WinForms).
&lt;/p&gt;
&lt;p&gt;
   This state of affairs is admittedly unfortunate.&amp;nbsp; We don’t properly separate
   out the truly fatal exceptions from those that we can gracefully recover from.&amp;nbsp;
   In an ideal world, I’d love to see us do that.&amp;nbsp; For example:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      At some point, we really ought to consider FailFast instead of continuing to run code
      under failures we know are fatal and dangerous to attempt to recover from, much like
      we do with SO.&amp;nbsp; At least these failures should be undeniable like thread aborts
      are.&amp;nbsp; But this is a fairly Byzantine response and is not for the faint of heart.&amp;nbsp;
      Given that we still live in a world where WinForms wraps the top-most frame of the
      GUI thread in a catch-all, presents a dialog box, and allows a user to click “Ignore
      &amp;amp; Continue”, I seriously doubt we’ll get there anytime soon. 
   &lt;li&gt;
      Never expose a ThreadAbortException to code in an AppDomain unless we can guarantee
      the AppDomain is being unloaded.&amp;nbsp; That means getting rid of the Abort API, and
      thus indirectly disallowing code from catching and calling ResetAbort.&amp;nbsp; It also
      means the A calls B calls C case would not allow B to unload until the thread voluntarily
      unwinds out of C. 
   &lt;li&gt;
      Allow OOMs to be caught only when they are soft.&amp;nbsp; That means a call to ‘new’,
      and it means the catch much occur inside the same stack frame as the call to ‘new’.&amp;nbsp;
      Such exceptions can be tolerated if code is properly written, and we will tell developed
      to be mindful of them.&amp;nbsp; Once such an OOM propagates past the calling stack frame,
      they will escalate to hard. 
   &lt;li&gt;
      All other OOMs are hard and fatal.&amp;nbsp; This includes failure to allocate memory
      to JIT code and failure to allocate 20 bytes to box an int.&amp;nbsp; Hard OOMs are thus
      undeniable. 
   &lt;li&gt;
      Get rid of ThreadInterruptedExceptions.&amp;nbsp; We screwed this up from Day One, and
      it’s probably too late to fix this.&amp;nbsp; We added cooperative cancellation in .NET
      4.0 for a reason. 
   &lt;li&gt;
      TypeInitializationExceptions can probably stay, but we should allow rerunning the
      cctor upon subsequent accesses.&amp;nbsp; Today, once a class C throws from its cctor,
      the class can never be constructed.&amp;nbsp; So on the current plan, it only makes sense
      to FailFast.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   I’m sure there are many other things we could do to improve things.&amp;nbsp; But these
   6 general themes would be a great start.
&lt;/p&gt;
&lt;p&gt;
   I’m just spitballing here.&amp;nbsp; There are no concrete plans to do any of&amp;nbsp;these
   6 things&amp;nbsp;as far as I know.&amp;nbsp; And at the end of the day, hardening only improves
   the statistics of the situation, so it tends to be very difficult to argue for one
   change over another, particularly if taking the change would make existing programs
   break.&amp;nbsp; But I really would like to see the base level of reliability in managed
   code improve with time.&amp;nbsp; Especially with the exciting work going on around &lt;a href="http://blogs.msdn.com/bclteam/archive/2009/02/23/preview-of-code-contract-tools-now-available-melitta-andersen.aspx"&gt;contract-checking
   in the BCL&lt;/a&gt;&amp;nbsp;in Visual Studio 10, I hope these topics become top-of-mind for
   folks again in the near future.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=223970c3-e1cc-4b09-9d61-99e8c5fae470" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx</comments>
      <category>Technology</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=07d734a8-245e-4b83-9295-9fdc18081dc8</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,07d734a8-245e-4b83-9295-9fdc18081dc8.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,07d734a8-245e-4b83-9295-9fdc18081dc8.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=07d734a8-245e-4b83-9295-9fdc18081dc8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      A developer from the Parallel Extensions team, <a href="http://www.igoro.com/">Igor
      Ostrovsky</a>, recently whipped together a really neat Silverlight game.  It's
      called <a href="http://www.robozzle.com/">RoboZZle</a>, and he calls it a "social
      puzzle game":
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      "RoboZZle is an online puzzle game that challenges players to program a robot to pick
      up all stars on a game board. The game mechanics are simple, yet allow for a wide
      variety of challenges that call for very different solution approaches." (from <a href="http://robozzle.com/blog/?p=3">the
      blog entry</a> introducing it.)
   </p>
        </blockquote>
        <p>
      The coolest feature of this game is that you win by programming.  And there's
      a whole community surrounding it, complete with forums, the ability to create your
      own games, a ranking system, its own blog and continuously updated news, etc. 
      Check it out.
   </p>
        <img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=07d734a8-245e-4b83-9295-9fdc18081dc8" />
      </body>
      <title>RoboZZle: a new social puzzle game</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,07d734a8-245e-4b83-9295-9fdc18081dc8.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/03/06/RoboZZleANewSocialPuzzleGame.aspx</link>
      <pubDate>Fri, 06 Mar 2009 23:36:36 GMT</pubDate>
      <description>&lt;p&gt;
   A developer from the Parallel Extensions team, &lt;a href="http://www.igoro.com/"&gt;Igor
   Ostrovsky&lt;/a&gt;, recently whipped together a really neat Silverlight game.&amp;nbsp; It's
   called &lt;a href="http://www.robozzle.com/"&gt;RoboZZle&lt;/a&gt;, and he calls it a "social
   puzzle game":
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   "RoboZZle is an online puzzle game that challenges players to program a robot to pick
   up all stars on a game board. The game mechanics are simple, yet allow for a wide
   variety of challenges that call for very different solution approaches." (from &lt;a href="http://robozzle.com/blog/?p=3"&gt;the
   blog entry&lt;/a&gt; introducing it.)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The coolest feature of this game is that you win by programming.&amp;nbsp; And there's
   a whole community surrounding it, complete with forums, the ability to create your
   own games, a ranking system, its own blog and continuously updated news, etc.&amp;nbsp;
   Check it out.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=07d734a8-245e-4b83-9295-9fdc18081dc8" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,07d734a8-245e-4b83-9295-9fdc18081dc8.aspx</comments>
      <category>Miscellaneous</category>
    </item>
    <item>
      <trackback:ping>http://www.bluebytesoftware.com/blog/Trackback.aspx?guid=72aaa68e-4cbd-41db-a7ce-ddc64411eafa</trackback:ping>
      <pingback:server>http://www.bluebytesoftware.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.bluebytesoftware.com/blog/PermaLink,guid,72aaa68e-4cbd-41db-a7ce-ddc64411eafa.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://www.bluebytesoftware.com/blog/CommentView,guid,72aaa68e-4cbd-41db-a7ce-ddc64411eafa.aspx</wfw:comment>
      <wfw:commentRss>http://www.bluebytesoftware.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=72aaa68e-4cbd-41db-a7ce-ddc64411eafa</wfw:commentRss>
      <slash:comments>22</slash:comments>
      <title>The magical dueling deadlocking spin locks</title>
      <guid>http://www.bluebytesoftware.com/blog/PermaLink,guid,72aaa68e-4cbd-41db-a7ce-ddc64411eafa.aspx</guid>
      <link>http://www.bluebytesoftware.com/blog/2009/02/24/TheMagicalDuelingDeadlockingSpinLocks.aspx</link>
      <pubDate>Tue, 24 Feb 2009 04:59:14 GMT</pubDate>
      <description>&lt;p&gt;
   Pop quiz: Can this code deadlock?
&lt;/p&gt;
&lt;span style="FONT-FAMILY: Consolas"&gt;&lt;font size=3&gt;&lt;font color=#000000&gt; &lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;SpinLock
   slockA = new SpinLock();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;SpinLock slockB
   = new SpinLock();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;
   &lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;Thread 1&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Thread
   2&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;~~~~~~~~&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;~~~~~~~~&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;slockA.Enter();&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;slockB.Enter();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;slockA.Exit();&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;slockB.Exit();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;slockB.Enter();&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;slockA.Enter();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;slockB.Exit();&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;slockA.Exit();&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&gt;
&lt;p&gt;
&lt;p&gt;
   The answer, as I'm sure you suspiciously&amp;nbsp;guessed, is "it depends."
&lt;/p&gt;
&lt;p&gt;
   I previously posted &lt;a href="http://www.bluebytesoftware.com/blog/2008/06/13/VolatileReadsAndWritesAndTimeliness.aspx"&gt;some
   thoughts&lt;/a&gt; about whether a full fence is required when exiting the lock.&amp;nbsp; In
   that post, I focused primarily on timeliness.&amp;nbsp; But what might be even more frightening
   is that the answer to my question above is yes, provided two things:
&lt;/p&gt;
&lt;p&gt;
   1. Exit doesn't end with a full fence.&lt;br&gt;
   2. Enter doesn't start with a full fence.
&lt;/p&gt;
&lt;p&gt;
   Just making Exit a store release and Enter a load acquire is insufficient.&amp;nbsp; Here's
   why.
&lt;/p&gt;
&lt;p&gt;
   Imagine a super simple spin lock that satisfies our deadlock criteria:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;class
   SpinLock {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;private
   volatile int m_taken;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   void Enter() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (m_taken == 0 &amp;amp;&amp;amp;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   m_taken, 1) == 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;
   &lt;o:p&gt;
      &lt;font color=#000000&gt;&amp;nbsp;&lt;/font&gt;
   &lt;/o:p&gt;
   &lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;public
   void Exit() {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Clearly Exit satisfies #1.&amp;nbsp; The technique of using an ordinary read of m_taken
   before resorting to the XCHG call is often known as a TATAS (test-and-test-and-set)
   lock, and this can help alleviate contention.&amp;nbsp; And it also means we will satisfy
   #2 above.
&lt;/p&gt;
&lt;p&gt;
   To see why deadlock is possible, imagine the following (fully legal) compiler transformation.&amp;nbsp;
   The compiler first inlines everything, so for Thread 1 we have:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;Thread
   1&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;~~~~~~~~&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (slockA.m_taken == 0 &amp;amp;&amp;amp;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockA.m_taken, 1) == 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockA.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (slockB.m_taken == 0 &amp;amp;&amp;amp;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockB.m_taken, 1) == 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockB.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   What has to happen next is pretty subtle.&amp;nbsp; It's even unlikely a compiler would
   do this intentionally (as far as I can tell).&amp;nbsp; But it's entirely legal to morph
   the above code into something like this:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;Thread
   1&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;~~~~~~~~&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (slockA.m_taken == 0 &amp;amp;&amp;amp;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockA.m_taken, 1) == 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (slockB.m_taken == 0) ;;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockA.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;if
   (Interlocked.CompareExchange(ref slockB.m_taken, 1) != 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;while
   (slockB.m_taken != 0 ||&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockB.m_taken, 1) != 0) ;;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockB.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   The load(s) of slockB.m_taken have moved before the store to slockA.m_taken; this
   is legal, even if they are both marked volatile.&amp;nbsp; A load acquire can move above
   a store release, and the code remains functionally equivalent.&amp;nbsp; Now, the code
   required to fix up this code motion is pretty hokey.&amp;nbsp; We clearly can't do the
   XCHG before the store to slockA.m_taken, so we need to try it afterwards.&amp;nbsp; But
   that brings about an awkward transformation: if it fails, we must effectively do what
   the original code did, spinning until we acquire the slockB lock.
&lt;/p&gt;
&lt;p&gt;
   Do you see the deadlock yet?
&lt;/p&gt;
&lt;p&gt;
   Imagine the compiler did similar code motion on Thread 2:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;Thread
   2&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;~~~~~~~~&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (true) {&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if
   (slockB.m_taken == 0 &amp;amp;&amp;amp;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockB.m_taken, 1) == 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;}&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;while
   (slockA.m_taken == 0) ;;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockB.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;if
   (Interlocked.CompareExchange(ref slockA.m_taken, 1) != 0)&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;while
   (slockA.m_taken != 0 ||&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Interlocked.Exchange(ref
   slockA.m_taken, 1) != 0) ;;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
   &lt;span style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: Consolas"&gt;&lt;font color=#000000&gt;slockA.m_taken
   = 0;&lt;o:p&gt;&lt;/o:p&gt;
   &lt;/font&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   Oh no!&amp;nbsp; See it now?
&lt;/p&gt;
&lt;p&gt;
   If Thread 1 and Thread 2 both enter the critical regions for slockA and slockB at
   the same times, they will end up spin-waiting for the other to leave before exiting
   their respective lock.
&lt;/p&gt;
&lt;p&gt;
   &lt;strong&gt;&lt;em&gt;Boom&lt;/em&gt;&lt;/strong&gt;: deadlock.
&lt;/p&gt;
&lt;p&gt;
   &lt;br&gt;
   &amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.bluebytesoftware.com/blog/aggbug.ashx?id=72aaa68e-4cbd-41db-a7ce-ddc64411eafa" /&gt;</description>
      <comments>http://www.bluebytesoftware.com/blog/CommentView,guid,72aaa68e-4cbd-41db-a7ce-ddc64411eafa.aspx</comments>
      <category>Technology</category>
    </item>
  </channel>
</rss>