<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fabulous Adventures In Coding : Threading</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx</link><description>Tags: Threading</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>What is this thing you call "thread safe"?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-thread-safe.aspx</link><pubDate>Mon, 19 Oct 2009 13:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9906219</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>29</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9906219.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9906219</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;STRONG&gt;Caveat: I am not an expert on multi-threading programming.&lt;/STRONG&gt; In fact, I wouldn't even say that I am &lt;EM&gt;competent&lt;/EM&gt; at it. My whole career, I've needed to write code to spin up a secondary worker thread probably less than half a dozen times. So take everything I say on the subject with some skepticism.&lt;/P&gt;
&lt;P&gt;A question I'm frequently asked: "&lt;EM&gt;is this code &lt;STRONG&gt;thread safe&lt;/STRONG&gt;?&lt;/EM&gt;" To answer the question, clearly we need to know what "thread safe" means.&lt;/P&gt;
&lt;P&gt;But before we get into that, there's something I want to clear up first. A question I am less frequently asked is "&lt;EM&gt;Eric, why does Michelle Pfeiffer always look so good in photographs?&lt;/EM&gt;"&amp;nbsp;To help answer this pressing question, I&amp;nbsp;consulted &lt;A class="" href="http://en.wikipedia.org/wiki/Photogenic" mce_href="http://en.wikipedia.org/wiki/Photogenic"&gt;Wikipedia&lt;/A&gt;:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;"A&amp;nbsp;&lt;B&gt;photogenic&lt;/B&gt; subject&amp;nbsp;is a subject that usually appears physically attractive or striking in photographs."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Why&amp;nbsp;does Michelle Pfeiffer always look so good in photographs? &lt;STRONG&gt;&lt;EM&gt;Because she's photogenic&lt;/EM&gt;.&lt;/STRONG&gt; Obviously.&lt;/P&gt;
&lt;P&gt;Well, I'm glad we've cleared up that mystery, but I seem to have wandered somehwat from the subject at hand. Wikipedia is &lt;A class="" href="http://en.wikipedia.org/wiki/Thread_safety" mce_href="http://en.wikipedia.org/wiki/Thread_safety"&gt;just as helpful in defining thread safety&lt;/A&gt;:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;&amp;nbsp;"A piece of code is &lt;B&gt;thread-safe&lt;/B&gt; if it functions correctly during simultaneous execution by multiple threads."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As with photogenicity, this&amp;nbsp;is obvious question-begging. When we ask "is this code &lt;EM&gt;thread safe&lt;/EM&gt;?" all we are really asking is "is this code &lt;EM&gt;correct&lt;/EM&gt; &lt;EM&gt;when called in a particular manner&lt;/EM&gt;?"&amp;nbsp;So how do we determine if the code is correct? &lt;STRONG&gt;We haven't actually explained anything here.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Wikipedia goes on:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;"In particular, it must satisfy the need for multiple threads to access the same shared data, ..."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;This seems fair; this scenario is almost always what people mean when they talk about thread safety. But then:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;"...and the need for a shared piece of data to be accessed by only one thread at any given time."&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;Now we're talking about techniques for &lt;EM&gt;creating&lt;/EM&gt; thread safety, not &lt;EM&gt;defining&lt;/EM&gt; what thread safety means. Locking data so that it can only be accessed by one thread at a time is just one possible&amp;nbsp;technique for creating thread safety; it is not itself the definition of thread safety.&lt;/P&gt;
&lt;P mce_keep="true"&gt;My point is not that the definition is &lt;EM&gt;wrong&lt;/EM&gt;; as informal definitions of thread safety&amp;nbsp;go, this one is not terrible.&amp;nbsp;Rather, my point is&amp;nbsp;that the&amp;nbsp;definition indicates that the concept itself is &lt;EM&gt;completely vague&lt;/EM&gt; and essentially means nothing more than "behaves correctly in some situations". Therefore, when I'm asked "is this code thread safe?" I always have to push back and ask "what are the &lt;EM&gt;exact&lt;/EM&gt; &lt;EM&gt;threading scenarios&lt;/EM&gt; you are concerned about?" and "exactly what is &lt;EM&gt;correct behaviour&lt;/EM&gt; of the object in every one of those scenarios?"&lt;/P&gt;
&lt;P mce_keep="true"&gt;Communication problems arise when&amp;nbsp;people with different answers to those questions try to communicate about thread safety. For example, suppose I told you that I have a "threadsafe mutable queue" that you can use in your program.&amp;nbsp;You then cheerfully write the following code that runs on one thread while another thread is busy adding and removing items from the mutable queue:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;if (!queue.IsEmpty) Console.WriteLine(queue.Peek());&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Your code then crashes when the Peek throws a QueueEmptyException. What is going on here? I&amp;nbsp;said this&amp;nbsp;thing was thread safe, and yet your code is crashing in a multi-threaded scenario.&lt;/P&gt;
&lt;P mce_keep="true"&gt;When I said "the queue is threadsafe" I meant that the queue maintains its internal state consistently no matter what sequence of &lt;EM&gt;individual&lt;/EM&gt; operations are happening on other threads. But I did not mean that you can use my queue in any scenario that requires &lt;EM&gt;logical consistency maintained across multiple operations in a sequence&lt;/EM&gt;. In short, my opinion of "correct behaviour" and your opinion of the same differed because what we thought of as the relevant scenario was completely different. I care only about not crashing, but you care about being able to reason logically about the information returned from each method call.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In this example, you and I are probably&amp;nbsp;talking about different kinds of thread safety. Thread safety of mutable data structures is usually all about ensuring that the operations on the shared data always operate on the &lt;STRONG&gt;most up-to-date&lt;/STRONG&gt; state of the shared data as it mutates, even if that means that a particular combination of operations appears to be &lt;STRONG&gt;logically inconsistent&lt;/STRONG&gt;, as in our example above. Thread safety of immutable data structures is all about ensuring that use of&amp;nbsp;the data across all operations is &lt;STRONG&gt;logically consistent&lt;/STRONG&gt;, at the expense of the fact that you're looking at an&amp;nbsp;immutable&amp;nbsp;snapshot that might be &lt;STRONG&gt;out-of-date&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The problem here is that the choice about whether to access the first element or not is based on "stale" data. Designing a truly thread-safe mutable data structure in a world where &lt;EM&gt;nothing is allowed to be stale&lt;/EM&gt; can be&amp;nbsp;very difficult. Consider what you'd have to do in order to make the "Peek" operation above actually threadsafe. You'd need a new method:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;if (!queue.Peek(out first)) Console.WriteLine(first);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Is this "thread safe"? It certainly seems better.&amp;nbsp;But what if after the Peek, a different thread dequeues the queue? Now you're not crashing, but you've changed the behaviour of the previous program considerably. In the previous program, if, after the test there was a dequeue on another thread that changed what the first element was, then you'd either crash or&amp;nbsp;print out the up-to-date first element in the queue. Now you're printing out a &lt;EM&gt;stale&lt;/EM&gt; first element. Is that &lt;EM&gt;correct&lt;/EM&gt;? Not if we &lt;EM&gt;always&lt;/EM&gt; want to operate on up-to-date data!&lt;/P&gt;
&lt;P mce_keep="true"&gt;But wait a moment -- actually, the &lt;EM&gt;previous&lt;/EM&gt; version of the code had this problem as well. What if the dequeue on the other thread happened &lt;EM&gt;after&lt;/EM&gt; the call to Peek succeeded but &lt;EM&gt;before&lt;/EM&gt; the Console.WriteLine call executed? Again, you could be printing out stale data.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What if you want to ensure that you are always printing out up-to-date data? What you really need to make this threadsafe is:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;queue.DoSomethingToHead(first=&amp;gt;{Console.WriteLine(first);});&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Now the queue&amp;nbsp;author and the queue user agree on what the relevant scenarios are, so this is truly threadsafe. Right?&lt;/P&gt;
&lt;P mce_keep="true"&gt;Except... there could be something super-complicated in that delegate. What if whatever is in the delegate happens to cause an event that triggers code to run on another thread, which in turn causes some queue operation to run, which in turn blocks in such a manner that we've produced a deadlock? Is a deadlock "correct behaviour"? And if not, is&amp;nbsp;this method truly "safe"?&lt;/P&gt;
&lt;P mce_keep="true"&gt;Yuck.&lt;/P&gt;
&lt;P mce_keep="true"&gt;By now you take my point I'm sure.&amp;nbsp;As I pointed out earlier, &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2008/08/19/tasty-beverages.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2008/08/19/tasty-beverages.aspx"&gt;it is unhelpful to say that a building or a hunk of code is "secure" without somehow communicating &lt;STRONG&gt;which&amp;nbsp;threats&lt;/STRONG&gt;&amp;nbsp;the utilized security mechanism are and are not&amp;nbsp;proof against.&lt;/A&gt; Similarly,&amp;nbsp;&lt;STRONG&gt;it is unhelpful to say that code is "thread safe" without somehow communicating what undesirable&amp;nbsp;behaviors the utilized thread safety mechanisms do and do not prevent.&lt;/STRONG&gt; "Thread safety" is nothing more nor less than a code contract, like any other code contract. You agree to talk to an object in a particular manner, and it agrees to give you correct results if you do so; working out exactly what that manner is, and what the correct responses are, is a potentially tough problem.&lt;/P&gt;
&lt;P mce_keep="true"&gt;************&lt;/P&gt;
&lt;P&gt;(*) Yes, I'm aware that if I think something on Wikipedia is wrong, I can change it. There are two reasons why I should not do so.&amp;nbsp;First, as&amp;nbsp;I've already stated I'm not an expert in this area; I leave it to the experts to sort out amongst themselves what the right thing to say here is. And second, my point is not that the Wikipedia page is wrong, but rather that it illustrates that the term itself is&amp;nbsp;vague by nature.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9906219" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Wikipedia/default.aspx">Wikipedia</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Michelle+Pfeiffer/default.aspx">Michelle Pfeiffer</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Begging+the+question/default.aspx">Begging the question</category></item><item><title>Events and Races</title><link>http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx</link><pubDate>Wed, 29 Apr 2009 15:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9571319</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9571319.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9571319</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Here’s a question &lt;A href="http://stackoverflow.com/questions/786383/c-events-and-thread-safety" mce_href="http://stackoverflow.com/questions/786383/c-events-and-thread-safety"&gt;similar&lt;/A&gt; to one I saw on &lt;A href="http://www.stackoverflow.com/" mce_href="http://www.stackoverflow.com"&gt;stackoverflow&lt;/A&gt; the other day. Suppose you have an event:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public event Action Foo; &lt;/SPAN&gt;
&lt;P&gt;The standard pattern for firing this event is: &lt;SPAN class=code&gt;
&lt;P&gt;Action temp = Foo;&lt;BR&gt;if (temp != null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temp();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What the heck is up with that? Why not just call “&lt;SPAN class=code&gt;Foo()&lt;/SPAN&gt;” ? &lt;/P&gt;
&lt;P&gt;First off, this pattern ensures that the thing that is invoked is not the null delegate reference, which would cause a null reference exception to be thrown. But if that’s what we want, then surely we could have skipped the temporary variable – just “&lt;SPAN class=code&gt;if (Foo != null) Foo();&lt;/SPAN&gt;” would do. Why the temp?&lt;/P&gt;
&lt;P&gt;The temporary variable ensures that this is “thread safe”. If the event’s handlers are being modified on another thread it is possible for Foo to be non-null at the point of the check, then set to null on a different thread, and then the invocation throws.&lt;/P&gt;
&lt;P&gt;Using the temporary variable effectively makes a copy of the current set of event handlers. Remember, &lt;STRONG&gt;multi-cast delegates are immutable&lt;/STRONG&gt;; when you add or remove a handler, you &lt;EM&gt;replace&lt;/EM&gt; the existing multi-cast delegate object with a &lt;EM&gt;different&lt;/EM&gt; delegate object that has different behaviour. You do not modify an existing &lt;EM&gt;object&lt;/EM&gt;, you modify the &lt;EM&gt;variable&lt;/EM&gt; that stores the event handler. Therefore, stashing away the current reference stored in that variable into a temporary variable effectively makes a copy of the current state.&lt;/P&gt;
&lt;P&gt;Is that clear? Make sure it is, because now things start to get really confusing.&lt;/P&gt;
&lt;P&gt;A common criticism of this pattern is that it trades one race condition for another. Let’s consider that scenario again more carefully:&lt;/P&gt;
&lt;P&gt;The event handler contains a single handler, H. Thread Alpha makes a copy of the delegate to H in temp and determines that it is not null. Thread Beta decides that H must no longer be called when the event is fired, so it sets the handler to null. Thread Beta then assumes that H will never be called, and destroys a bunch of state that H needs to execute successfully. Thread Alpha then regains control and executes H, which behaves crazily since its necessary state has been destroyed. Thread Beta’s attempt to ensure that H is not called has been defeated by the race condition.&lt;/P&gt;
&lt;P&gt;A frequently-stated principle of good software design is that code which calls attention to bugs by throwing exceptions is better than code which hides bugs by muddling on through and doing the wrong thing. This code has a race condition that results in incorrect behaviour. Perhaps an application of that principle is to stop using a temporary and instead crash if it races. That is to say, this code has a failure mode; surely it is better to highlight that failure with a crisp exception than to turn it into crazy wrong behaviour.&lt;/P&gt;
&lt;P&gt;That seems plausibly argued, I agree, but the conclusion is wrong. &lt;/P&gt;
&lt;P&gt;Suppose we remove the temporary variable but keep the null check. Does that &lt;EM&gt;solve&lt;/EM&gt; the problem? No! We still have the same race conditions. Suppose the event handler delegate contains a reference to H. Thread Alpha checks to see whether it is null; it is not. Thread Alpha pushes the object to invoke on the runtime stack. &lt;EM&gt;Between the push of the delegate value and the call to invoke it, thread Beta sets the event handler to null.&lt;/EM&gt; And once again, H will be invoked after thread Beta has removed the handler.&lt;/P&gt;
&lt;P&gt;Suppose we remove the temporary &lt;EM&gt;and&lt;/EM&gt; the null check and just invoke the delegate directly. Does that help? No, we &lt;EM&gt;still&lt;/EM&gt; have the same race condition. The contents of the event handling variable can still be changed between the push of the delegate object onto the stack and the invocation of the delegate.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Removing the code around the call site does not decrease the number of race conditions in the code, and it does increase the number of crashes. Worse, doing so makes the race condition harder to detect by shrinking the window in which the race can occur without eliminating it. &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Removing the null check and/or the temporary is a bad idea; the already-bad situation is only made worse.&lt;/P&gt;
&lt;P&gt;Essentially there are two problems here that are being conflated. The two problems are:&lt;/P&gt;
&lt;P&gt;1) The event handler delegate can be null at any time.&lt;BR&gt;2) A “stale” handler can be invoked even after it has been removed.&lt;/P&gt;
&lt;P&gt;These two problems are actually orthogonal and have different solutions. The onus for solving the first problem is laid upon the &lt;EM&gt;code which does the invocation&lt;/EM&gt;; it is required to ensure that it does not dereference null. The store-in-temporary-and-test pattern ensures that null is never dereferenced. (There are other ways to solve this problem; for example, initializing the handler to have an empty action that is never removed. But doing a null check is the standard pattern.)&lt;/P&gt;
&lt;P&gt;The onus for solving the second problem is laid upon &lt;EM&gt;the code being invoked&lt;/EM&gt;; &lt;STRONG&gt;event handlers are required to be robust in the face of being called even after the event has been unsubscribed.&lt;/STRONG&gt; In the scenario I described, &lt;STRONG&gt;the bug is actually in H&lt;/STRONG&gt;. It needs to be robust enough to check to see whether the state it needs is still there, and bail out cleanly if it is not. (Or, alternatively,&amp;nbsp;some additional locking mechanism needs to be implemented which ensures that the&amp;nbsp;code which fires the event cooperates with the code that changes the event handlers to ensure&amp;nbsp;the desired behaviour.)&lt;/P&gt;
&lt;P&gt;The point though is that the "null ref problem" and the "stale handler problem"&amp;nbsp;are two&amp;nbsp;separate problems that are easily confused because the symptoms of both arise at the exact same call site code. You've got to solve &lt;EM&gt;both&lt;/EM&gt; problems if you want to do threadsafe events. How you do so is up to you; just don't confuse the solution of one problem&amp;nbsp;for a solution of&amp;nbsp;the other.&lt;/P&gt;
&lt;P&gt;(Thanks to Microsofties Levi Broderick, Chris Burrows, Curt Hagenlocher and Wolf Logan; this article is based on a conversation about their analysis of this pattern.)&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9571319" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Quality/default.aspx">Code Quality</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Metablogging/default.aspx">Metablogging</category></item><item><title>Locks and exceptions do not mix</title><link>http://blogs.msdn.com/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx</link><pubDate>Fri, 06 Mar 2009 19:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9460149</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>38</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9460149.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9460149</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;A couple years ago I wrote a bit about how our codegen for the lock statement could sometimes lead to situations in which an unoptimized build had &lt;A href="http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx"&gt;different potential deadlocks&lt;/A&gt; than an optimized build of the same source code. This is unfortunate, so we've fixed that for C# 4.0. However, all is still not rainbows, unicorns and Obama, as we'll see.&lt;/P&gt;
&lt;P&gt;Recall that &lt;SPAN class=code&gt;lock(obj){body}&lt;/SPAN&gt; was a syntactic sugar for &lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var temp = obj;&lt;BR&gt;Monitor.Enter(temp);&lt;BR&gt;try { body }&lt;BR&gt;finally { Monitor.Exit(temp); }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The problem here is that if the compiler generates a no-op instruction between the monitor enter and the try-protected region then it is possible for the runtime to throw a thread abort exception after the monitor enter but before the try. In that scenario, the finally never runs so the lock leaks, probably eventually deadlocking the program. It would be nice if this were impossible in unoptimized and optimized builds.&lt;/P&gt;
&lt;P&gt;In C# 4.0 we've changed lock so that it now generates code as if it were&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;bool lockWasTaken = false;&lt;BR&gt;var temp = obj;&lt;BR&gt;try { Monitor.Enter(temp, ref lockWasTaken); { body } }&lt;BR&gt;finally { if (lockWasTaken) Monitor.Exit(temp); }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The problem now becomes someone else's problem; the implementation of Monitor.Enter takes on responsibility for atomically setting the flag in a manner that is immune to thread abort exceptions messing it up. &lt;/P&gt;
&lt;P&gt;So everything is good now, right?&lt;/P&gt;
&lt;P&gt;Sadly, no. It's &lt;EM&gt;consistently bad&lt;/EM&gt; now, which is better than being inconsistently bad. But there's an enormous problem with this approach. By choosing these semantics for "lock" we have made a potentially unwarranted and dangerous choice on your behalf; &lt;STRONG&gt;implicit in this codegen is the belief that a deadlocked program is the worst thing that can happen&lt;/STRONG&gt;. That's not necessarily true! &lt;STRONG&gt;Sometimes deadlocking the program is the better thing to do -- the lesser of two evils.&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The &lt;EM&gt;purpose&lt;/EM&gt; of the lock statement is to help you protect the integrity of a mutable resource that is shared by multiple threads.&amp;nbsp;But suppose an exception is thrown halfway through a mutation of the locked resource. Our implementation of lock does not magically roll back the mutation to its pristine state, and it does not complete the mutation. Rather, control &lt;EM&gt;immediately&lt;/EM&gt; branches to the finally, releasing the lock and allowing every other thread that is patiently waiting to&amp;nbsp;&lt;EM&gt;immediately&lt;/EM&gt; view the messed-up partially mutated state! If that state has privacy, security, or human life and safety implications, the result could be very bad indeed. In that case it is &lt;EM&gt;possibly&lt;/EM&gt; better to deadlock the program and protect the messed-up resource by denying access to it entirely. But that's obviously not good either.&lt;/P&gt;
&lt;P&gt;Basically, we all have a difficult choice to make whenever doing multi-threaded programming. We can (1) automatically release locks upon exceptions, exposing inconsistent state and living with the resulting bugs (bad)&amp;nbsp;(2) maintain locks upon exceptions, deadlocking the program (arguably often worse)&amp;nbsp;or (3) carefully implement the bodies of locks that&amp;nbsp;do mutations so that in the event of an exception, the mutated resource is rolled back to a pristine state before the lock is released. (Good, but hard.)&lt;/P&gt;
&lt;P&gt;This is yet another reason why &lt;STRONG&gt;the body of a lock should do as little as possible&lt;/STRONG&gt;. Usually the rationale for having small lock bodies is to get in and get out quickly, so that anyone waiting on the lock does not have to wait long. But an even better reason is because small, simple lock bodies minimize the chance that the thing in there is going to throw an exception. It's also easier to rewrite mutating lock bodies to have rollback behaviour if they don't do very much to begin with.&lt;/P&gt;
&lt;P&gt;And of course, this is yet another reason why aborting a thread is pure evil. Try to never do so!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9460149" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>Arrays considered somewhat harmful</title><link>http://blogs.msdn.com/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx</link><pubDate>Mon, 22 Sep 2008 21:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8961437</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>58</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8961437.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8961437</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I got a moral question from an author of programming language textbooks the other day requesting my opinions on whether or not beginner programmers should be taught how to use arrays.&lt;/P&gt;
&lt;P&gt;Rather than actually answer that question, I gave him a long&amp;nbsp;list of my opinions about&amp;nbsp;arrays, how I use arrays, how&amp;nbsp;we expect arrays to be used in the future, and so on. This gets a bit long, but like Pascal, I didn't have time to make it shorter.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Let me start by saying when you definitely should not use arrays, and then wax more philosophical about the future of modern programming and the role of the array in the coming world.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;You probably should not return an array as the value of a public method or property&lt;/STRONG&gt;, particularly when the information content of the array is logically immutable. Let me give you an example of where we got that horridly wrong in a very visible way in the framework.&amp;nbsp; If you take a look at the documentation for System.Type, you'll find that&amp;nbsp;just looking at the method descriptions gives one a sense of existential dread. One sees a whole lot of sentences like &lt;EM&gt;"Returns an array of Type objects that represent the constraints on the current generic type parameter." &lt;/EM&gt;Almost every method on System.Type returns an array it seems.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Now think about how that must be implemented. When you call, say, GetConstructors() on typeof(string), the implementation cannot possibly do this, as sensible as it seems.&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class Type { &lt;BR&gt;&amp;nbsp;&amp;nbsp; private ConstructorInfo[] ctorInfos;&lt;BR&gt;&amp;nbsp;&amp;nbsp; public ConstructorInfo[] GetConstructors()&lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ctorInfos == null) ctorInfos = GoGetConstructorInfosFromMetadata();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ctorInfos;&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Why? Because now the caller can take that array and &lt;EM&gt;replace the contents of it with whatever they please&lt;/EM&gt;. Returning an array means that &lt;STRONG&gt;you have to make a fresh copy of the array every time you return it&lt;/STRONG&gt;. You get called a hundred times, you’d better make a hundred array instances, no matter how large they are. It’s a performance nightmare – particularly if, like me, you are considering&amp;nbsp;using reflection to &lt;EM&gt;build a compiler&lt;/EM&gt;. Do you have any idea how many times a second I try to get type information out of reflection?&amp;nbsp; Not nearly as many times as I could; every time I do it’s another freakin’ array allocation!&lt;/P&gt;
&lt;P&gt;The frameworks designers were not foolish people; unfortunately, we did not have generic types in .NET 1.0. clearly the sensible thing now for GetConstructors() to return is IList&amp;lt;ConstructorInfo&amp;gt;. You can build yourself a nice read-only collection object once, and then just pass out references to it as much as you want. &lt;/P&gt;
&lt;P&gt;What is the root cause of this malaise? It is simple to state: The caller is requesting &lt;EM&gt;values&lt;/EM&gt;.&amp;nbsp; The callee fulfills the request by handing back &lt;EM&gt;variables&lt;/EM&gt;. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;An array is a collection of variables.&lt;/STRONG&gt; The caller doesn’t &lt;EM&gt;want&lt;/EM&gt; variables, but it’ll take them if that’s the only way to get the values. But in this case, as in most cases, &lt;EM&gt;neither the callee nor the caller wants those variables to ever vary&lt;/EM&gt;. Why on earth is the callee passing back variables then? &lt;STRONG&gt;Variables vary&lt;/STRONG&gt;. Therefore, a fresh, different variable must be passed back every time, so that if it does vary, nothing bad happens to anyone else who has requested the same values.&lt;/P&gt;
&lt;P&gt;If you are writing such an API, wrap the array in a ReadOnlyCollection&amp;lt;T&amp;gt; and return an IEnumerable&amp;lt;T&amp;gt; or an IList&amp;lt;T&amp;gt; or something, but not an array.&amp;nbsp; (And of course, do not simply cast the array to IEnumerable&amp;lt;T&amp;gt; and think you’re done!&amp;nbsp; That is still passing out variables; the caller can simply cast back to array!&amp;nbsp; Only pass out an array if it is wrapped up by a read-only object.)&lt;/P&gt;
&lt;P&gt;That’s the situation at present. What are the implications of array characteristics for the future of programming and programming languages?&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Parallelism Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;The physics aspects of Moore’s so-called “Law” are failing, as they eventually must. Clock speeds have stopped increasing, transistor density has stopped increasing. The laws of thermodynamics and the Uncertainty Principle are seeing to that. But manufacturing costs per chip are still falling, which means that our only hope of Moore’s "Law" continuing to hold over the coming decades is to cram more and more processors into each box.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We’re going to need programming languages that allow mere mortals to write code that is parallelizable to multiple cores.&lt;/P&gt;
&lt;P&gt;Side-effecting change is the enemy of parallelization. Parallelizing in a world with observable side effects means locks, and locks means choosing between implementing lock ordering and dealing with random crashes or deadlocks. Lock ordering requires global knowledge of the program. Programs are becoming increasingly complex, to the point where one person cannot reasonably and confidently have global knowledge. Indeed, we prefer programming languages to have the property that programs in them can be understood by understanding one part at a time, not having to swallow the whole thing in one gulp.&lt;/P&gt;
&lt;P&gt;Therefore we tools providers need to create ways for people to program effectively &lt;EM&gt;without causing observable side effects&lt;/EM&gt;. &lt;/P&gt;
&lt;P&gt;Of all the sort of “basic” types, &lt;STRONG&gt;arrays most strongly work against this goal&lt;/STRONG&gt;. An array’s whole purpose is to be a mass of mutable state. Mutable state is hard for both humans and compilers to reason about. It will be hard for us to write compilers in the future that generate performant multi-core programs if developers use a lot of arrays.&lt;/P&gt;
&lt;P&gt;Now, one might reasonably point out that List&amp;lt;T&amp;gt; is a mass of mutable state too. But at least one could create a threadsafe list class, or an immutable list class, or a list class that has transactional integrity, or&amp;nbsp;uses some form of isolation&amp;nbsp;or whatever. We have an extensibility model for lists because &lt;EM&gt;lists are classes&lt;/EM&gt;. We have no ability to make an “immutable array”. Arrays are what they are and they’re never going to change.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Conceptual Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;We want C# to be a language in which one can draw a line between code that implements a mechanism and code that implements a policy. &lt;/P&gt;
&lt;P&gt;The “C” programming language is all about mechanisms. It lays bare almost exactly what the processor is actually doing, providing only the thinnest abstraction over the memory model. And though we want you to be able to write programs like that in C#, most of the time people should be writing code in the “policy” realm. That is, code that emphasizes &lt;EM&gt;what the code is supposed to do, &lt;/EM&gt;not &lt;EM&gt;how it does it.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Coding which is more declarative than imperative, coding which avoids side effects, coding which emphasizes algorithms and purposes over mechanisms, that kind of coding is the future in a world of parallelism. (And you’ll note that LINQ is designed to be declarative, strongly abstract away from mechanisms, and be free of side effects.)&lt;/P&gt;
&lt;P&gt;Arrays work against all of these factors. Arrays demand imperative code, arrays are all about side effects, arrays make you write code which emphasizes how the code works, not what the code is doing or why it is doing it. Arrays make optimizing for things like “swapping two values” easy, but destroy the larger ability to optimize for parallelism.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Practical Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;And finally, given that arrays are mutable by design, the way an array restricts that mutability is deeply weird. All the &lt;EM&gt;contents&lt;/EM&gt; of the collection are mutable, but the &lt;EM&gt;size&lt;/EM&gt; is fixed.&amp;nbsp; What is up with that? Does that solve a problem anyone actually has?&lt;/P&gt;
&lt;P&gt;For this reason alone I do almost no programming with arrays anymore. Arrays simply do not model any problem that I have at all well – I rarely need a collection which has the rather contradictory properties of being &lt;EM&gt;completely mutable&lt;/EM&gt;, and at the same time, &lt;EM&gt;fixed in size&lt;/EM&gt;. If I want to mutate a collection it is almost always to add something to it or remove something from it, not to change what value an index maps to.&lt;/P&gt;
&lt;P&gt;We have a class or interface for everything I need. If I need a sequence I’ll use IEnumerable&amp;lt;T&amp;gt;, if I need a mapping from contiguous numbers to data I’ll use a List&amp;lt;T&amp;gt;, if I need a mapping across arbitrary data I’ll use a Dictionary&amp;lt;K,V&amp;gt;, if I need a set I’ll use a HashSet&amp;lt;T&amp;gt;. I simply don’t need arrays for anything, so I almost never use them. They don’t solve a problem I have better than the other tools at my disposal.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Pedagogic Problems&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;It is&amp;nbsp;important that beginning programmers understand arrays; it is an important and widely used concept. But it is also important to me that they understand the weaknesses and shortcomings of arrays. In almost every case, there is a better tool to use than an array.&lt;/P&gt;
&lt;P&gt;The difficulty is, pedagogically, that it is hard to discuss the merits of those tools without already having down concepts like classes, interfaces, generics, asymptotic performance, query expressions, and so on. It’s a hard problem for the writer and for the teacher. Fortunately, for me, it's not a problem that I personally have to solve.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8961437" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rants/default.aspx">Rants</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Quality/default.aspx">Code Quality</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Software+development+methodology/default.aspx">Software development methodology</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Immutability/default.aspx">Immutability</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Arrays/default.aspx">Arrays</category></item><item><title>Subtleties of C# IL codegen</title><link>http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx</link><pubDate>Fri, 17 Aug 2007 19:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4432044</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>23</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/4432044.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=4432044</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;It must be CLR week over at &lt;A class="" href="http://blogs.msdn.com/oldnewthing/" mce_href="http://blogs.msdn.com/oldnewthing/"&gt;The Old New Thing&lt;/A&gt; because it's been non-stop posts about C# lately.&amp;nbsp;Raymond's last two technical posts have been about &lt;A class="" href="http://blogs.msdn.com/oldnewthing/archive/2007/08/16/4407029.aspx" mce_href="http://blogs.msdn.com/oldnewthing/archive/2007/08/16/4407029.aspx"&gt;null checks&lt;/A&gt; and &lt;A class="" href="http://blogs.msdn.com/oldnewthing/archive/2007/08/17/4422794.aspx" mce_href="http://blogs.msdn.com/oldnewthing/archive/2007/08/17/4422794.aspx"&gt;no-op instructions&lt;/A&gt; generated by the jitter when translating IL into machine code.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'll comment on both posts here, but I want to get the no-op discussion done first, because there are some subtleties here I believe that Raymond's statement that the jitter does not generate no-ops when not debugging is not entirely correct. This is not a mere nitpick -- as we'll see, whether it does so or not actually has semantic relevance in rare stress cases.&lt;/P&gt;
&lt;P&gt;Now, I'll slap a disclaimer of my own on here: I know way more about the compiler than the jitter/debugger interaction. This is &lt;EM&gt;my&lt;/EM&gt; understanding of how it works. If someone who actually works on the jitter would like to confirm my and Raymond's interpretation of what we see going on here, I'd welcome that.&lt;/P&gt;
&lt;P&gt;Before I get into the details, let me point out that in the C# compiler, "debug info emitting on/off" and "IL optimizations on/off" are &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2005/10/28/483905.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/10/28/483905.aspx"&gt;orthogonal&lt;/A&gt; settings. One controls whether debug info is emitted, the other controls what IL the code generator spits out. It is sensible to set them as opposites but you certainly do not have to.&lt;/P&gt;
&lt;P&gt;With optimizations off, the C# compiler emits no-op IL instructions all over the place.&amp;nbsp; With debug info on and optimizations off, some of those no-ops will be there to be targets of breakpoints for statements or fragments of expressions which would otherwise be hard to put a breakpoint on. &lt;/P&gt;
&lt;P&gt;The jitter then cheerfully turns IL no-ops into x86 no-ops. &lt;EM&gt;I suspect that it does so whether there is a debugger attached or not&lt;/EM&gt;. &lt;/P&gt;
&lt;P&gt;Furthermore, I have not heard that the jitter ever manufactures no-ops out of whole cloth &lt;EM&gt;for debugging purposes&lt;/EM&gt;, as Raymond implies. I suspect -- but I have not verified -- that if you compile your C# program with debug info on AND optimizations on, then you'll see a lot fewer no-ops in the jitted code (and your debugging experience will be correspondingly worse). The jitter may of course generate no-ops for other purposes -- padding code out to word boundaries, etc.&lt;/P&gt;
&lt;P&gt;Now we come to the important point: &lt;STRONG&gt;It is emphatically NOT the case that a no-op cannot affect the behaviour of a program, as many people incorrectly believe.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In C#, &lt;SPAN class=code&gt;lock(expression) statement&lt;/SPAN&gt; is a syntactic sugar for something like&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;temp = expression;&lt;BR&gt;System.Threading.Monitor.Enter(temp); &lt;BR&gt;try { statement } finally { System.Threading.Monitor.Exit(temp); } &lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The x86 jitter has the nice property that the code it generates guarantees that an exception is never thrown between the &lt;SPAN class=code&gt;Enter&lt;/SPAN&gt; and the &lt;SPAN class=code&gt;try&lt;/SPAN&gt;. This means that the &lt;SPAN class=code&gt;finally&lt;/SPAN&gt; always executes if the lock has been taken, which means that the locked resource is always unlocked. &lt;/P&gt;
&lt;P&gt;That is, unless the C# compiler generates a no-op IL instruction between the &lt;SPAN class=code&gt;Enter&lt;/SPAN&gt; and the &lt;SPAN class=code&gt;try&lt;/SPAN&gt;! The jitter turns that into a no-op x86 instruction, and it is possible for another thread to cause a thread abort exception while the thread that just took the lock is in the no-op. This is a long-standing bug in C# which we will unfortunately not be fixing for C# 3.0.&lt;/P&gt;
&lt;P&gt;If the scenario I've described happens then the &lt;SPAN class=code&gt;finally&lt;/SPAN&gt; will never be run, the lock will never be released and hey, now we're just begging for a deadlock.&lt;/P&gt;
&lt;P&gt;That's the only situation I know of in which emitting a no-op can cause a serious semantic change in a program -- turning a working program into a deadlocking one. And that sucks. &lt;/P&gt;
&lt;P&gt;I've been talking with some of the CLR jitter and threading guys about ways we can fix this more robustly than merely removing the no-op. I'm hoping we'll figure something out for some future version of the C# language.&lt;/P&gt;
&lt;P&gt;As for the bit about emitting null checks: indeed, at the time of a call to an instance method, whether virtual or not, we guarantee that the object of the call is not null by throwing an exception if it is. The way this is implemented in IL is a little odd. There are two instructions we can emit: &lt;SPAN class=code&gt;call&lt;/SPAN&gt;, and &lt;SPAN class=code&gt;callvirt&lt;/SPAN&gt;. &lt;SPAN class=code&gt;call&lt;/SPAN&gt; does NOT do a null check and does a non-virtual call. &lt;SPAN class=code&gt;callvirt&lt;/SPAN&gt; does do a null check and does a virtual call if it is a virtual method, or a non-virtual call if it is not.&lt;/P&gt;
&lt;P&gt;If you look at the IL generated for a non-virtual call on an instance method, you'll see that sometimes we generate a &lt;SPAN class=code&gt;call&lt;/SPAN&gt;, sometimes we generate a &lt;SPAN class=code&gt;callvirt&lt;/SPAN&gt;. Why? We generate the &lt;SPAN class=code&gt;callvirt&lt;/SPAN&gt; when we want to force the jitter to generate a null check. We generate a &lt;SPAN class=code&gt;call&lt;/SPAN&gt; when we know that no null check is necessary, thereby allowing the jitter to skip the null check and generate slightly faster and smaller code.&lt;/P&gt;
&lt;P&gt;When do we know that the null check can be skipped? If you have something like &lt;SPAN class=code&gt;(new Foo()).FooNonVirtualMethod()&lt;/SPAN&gt; we know that the allocator never returns null, so we can skip the check. It's a nice, straightforward optimization, but the realization in the IL is a bit subtle.&lt;BR&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4432044" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Generation/default.aspx">Code Generation</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>Human sacrifice, dogs and cats living together, mass hysteria! and thread model errors!</title><link>http://blogs.msdn.com/ericlippert/archive/2007/05/07/human-sacrifice-dogs-and-cats-living-together-mass-hysteria-and-thread-model-errors.aspx</link><pubDate>Tue, 08 May 2007 02:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2482620</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/2482620.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=2482620</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Reader Shaka comments on &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2006/07/07/659259.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2006/07/07/659259.aspx"&gt;my post about error messages&lt;/A&gt; that "catastrophic failure" really does take the cake as being a terrible error message.&lt;/P&gt;
&lt;P&gt;I fondly remember the first time I saw "catastrophic failure" as an error message. I was an intern, running the build lab for Visual Basic for Applications, and I was trying to get the PowerPC cross-compiler working so that we could build PPC binaries on x86 hardware. (Note that this was in the early 1990's. The VS build lab is now an entire team of people who have dedicated circuits just for the cooling equipment for all their computers. We've come a long way from an intern, a closet, and six machines named after opponents of Godzilla (*).)&lt;/P&gt;
&lt;P&gt;Anyway, the compiler had a bug which caused it to run out of stack while compiling a particular module and the error was "catastrophic failure". This amused me to no end at the time. I laughed out loud, literally. I mean, &lt;EM&gt;fatal&lt;/EM&gt;, sure. That process is going &lt;EM&gt;down&lt;/EM&gt;. But "catastrophic"? I expect catastrophes to at least result in my hard disk becoming unreadable. I want bridges collapsing and floods and &lt;A href="http://frogstar.soylentgeek.com/wav/disaster.wav"&gt;mass hysteria&lt;/A&gt;!&lt;/P&gt;
&lt;P&gt;I have therefore always been rather embarrassed that the error message you get when you call the script engine on the &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx"&gt;wrong thread&lt;/A&gt; is "catastrophic failure". That, unfortunately, is the somewhat breathless and overstated string associated with &lt;SPAN class=code&gt;E_UNEXPECTED&lt;/SPAN&gt;. Basically we want to say "you called us in a completely unexpected way which thoroughly violates the engine contract, please don't do that". But "catastrophic failure" is what you get. I wish now that we'd declared a new &lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/10/22/53267.aspx"&gt;HRESULT&lt;/A&gt; just for "you've violated the engine contract". But it's far, far too late now.&lt;/P&gt;
&lt;P&gt;(*) In the interests of total accuracy: the OLE Automation build machines were named after Godzilla's opponents: Mothra, Monster Zero, etc. The VBA build machines were named after species of marine mammals: sei, humpback, etc.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2482620" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>The Tragedy of Thread Happiness Disease</title><link>http://blogs.msdn.com/ericlippert/archive/2004/02/15/the-tragedy-of-thread-happiness-disease.aspx</link><pubDate>Sun, 15 Feb 2004 19:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:73366</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/73366.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=73366</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A &lt;A title=http://www.joelonsoftware.com/ href="http://www.joelonsoftware.com/"&gt;JOS&lt;/A&gt; reader interested in developing server software asked recently 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Is it possible to determine the number of concurrent threads a server can support from the server's specification?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now, as I've said &lt;A title=http://blogs.msdn.com/ericlippert/archive/2003/12/01/53411.aspx href="http://blogs.msdn.com/ericlippert/archive/2003/12/01/53411.aspx"&gt;before&lt;/A&gt;, I'm no expert on performance tuning multi-threaded applications, but I have picked up a thing or two hanging around the real experts on the IIS team.&amp;nbsp; In fact, the perf teams get questions in this vein all the time from customers, both internal and external.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The interesting thing about the question is that it is symptomatic of &lt;B&gt;&lt;SPAN&gt;Thread Happiness&lt;/SPAN&gt;&lt;/B&gt;, a peculiar disease which usually strikes programmers who are relatively new to large-scale multi-threaded software development.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;How do I know that the questioner is getting Thread Happy?&amp;nbsp; Because if they were writing an application where there were two threads or five threads or ten threads then they wouldn't be asking &lt;I&gt;&lt;SPAN&gt;that&lt;/SPAN&gt;&lt;/I&gt; question.&amp;nbsp; They'd be asking "&lt;B&gt;&lt;SPAN&gt;I want to write a server app with two/five/ten/whatever threads -- how buff does the server have to be?"
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;But they're asking the question &lt;B&gt;&lt;SPAN&gt;"&lt;I&gt;&lt;SPAN&gt;how many&lt;/SPAN&gt;&lt;/I&gt; threads can I create on a given server?"&lt;/SPAN&gt;&lt;/B&gt; so I can only assume that they are thinking of writing some application that is going to create a &lt;B&gt;&lt;SPAN&gt;large&lt;/SPAN&gt;&lt;/B&gt; and &lt;B&gt;&lt;SPAN&gt;variable&lt;/SPAN&gt;&lt;/B&gt; number of threads, &lt;STRONG&gt;as many as possible&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;That's Thread Happiness right there.&amp;nbsp; Don't do that!&amp;nbsp; It's almost certainly a bad design.&amp;nbsp; Massively multi-threaded applications cause more problems than they solve; they are very difficult to get correct, and even harder to get performant.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;To actually answer the question, no, there's no way of telling that from the server spec. Why?&amp;nbsp; Because there is nowhere near enough information in the "static" facts about the hardware.&amp;nbsp; Server application threading performance depends on "dynamic" facts like: &lt;BR&gt;&lt;BR&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What other processes are going to be running?&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What are those threads going to be doing?&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How much memory do you have free?&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How much contention, locking, busy waiting, context switching, blah blah blah, is there going to be?&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What are the performance metrics that will determine when things have gotten too bad.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;So, in short, don't even go there.&amp;nbsp; Come up with a design that uses a small number of threads and tune that.&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now, you might be wondering "What about real-world server applications which do spin up a variable number of threads then?&amp;nbsp; How do they decide how many is too many?"&lt;BR&gt;&lt;BR&gt;It's quite hard.&amp;nbsp; These things used to be configurable in IIS, but a few years back the IIS team had the realization that (a) you can't expect a human being to figure out what the ideal thread limit is, and (b) the ideal thread limit changes dynamically because of all the factors I mentioned above.&lt;BR&gt;&lt;BR&gt;IIS therefore keeps a relatively small thread pool, and continually monitors its own performance, tweaking the thread pool count, thread priorities, etc, as conditions change.&amp;nbsp; It tries to keep the server well-tuned dynamically.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;This was non-trivial code to write.&amp;nbsp; Though I've done quite a bit of optimization of software that runs in-process with IIS, the details of the IIS thread timing algorithms are way, way beyond my skills.&amp;nbsp; I wouldn't recommend such an approach unless you've got a lot of experience in the field.&amp;nbsp; A huge performance lab with a wide range of server hardware and a dedicated staff of experienced performance testers doesn't hurt either!&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=73366" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>Speeding Can Slow You Down</title><link>http://blogs.msdn.com/ericlippert/archive/2003/12/01/speeding-can-slow-you-down.aspx</link><pubDate>Tue, 02 Dec 2003 01:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53411</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53411.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53411</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I hope all you readers living in the United States had a restful and enjoyable Thanksgiving holiday. I sure did. 
&lt;P&gt;I've been meaning to talk a bit about some of the performance issues you run into when tuning massively multi-threaded applications, like the ASP engine.&amp;nbsp; I'd like to start off by saying that I am by no means an expert in this field, but I have picked up a thing or two from the real experts on the ASP perf team over the years. 
&lt;P&gt;One of the most intriguing things about tuning multi-threaded applications is that &lt;STRONG&gt;making the code faster can slow it down.&lt;/STRONG&gt; How is that possible? It certainly seems counter-intuitive, doesn't it? &lt;/P&gt;
&lt;P&gt;Let me give you an analogy.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Suppose you have an unusual road system in your town.&amp;nbsp; You have a square grid of roads with stoplights at the intersections.&amp;nbsp;But unlike the real world, these are &lt;EM&gt;perfect&lt;/EM&gt; traffic lights -- they are only red if there actually is another car in the intersection.&amp;nbsp;Unlike a normal road, each road goes only one way, and has at most one car on it at a time.&amp;nbsp; Once a car reaches the end of the road, it disappears and a new car may appear at the start. Furthermore, there is a small number of drivers -- typically one or two, but maybe eight or sixteen, but probably not one for every car. The drivers drive a car for a while, then stop it and run to the next car!&amp;nbsp; The drivers are pretty smart -- if their car is stopped at a red stoplight then they'll run to a stopped car that is not at a red stoplight (if one exists) and drive it for a while.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In our analogy each road represents a &lt;STRONG&gt;thread&lt;/STRONG&gt; and each stoplight represents a &lt;STRONG&gt;mutex&lt;/STRONG&gt;.&amp;nbsp; A mutex is a "mutually exclusive" section of code, also known as a "critical section".&amp;nbsp; Only one thread can be executing in that code at one time. The car represents the position of the &lt;STRONG&gt;instruction counter&lt;/STRONG&gt; in this thread.&amp;nbsp; When the car reaches the end of the road, the task is finished -- the page is served.&amp;nbsp;The drivers represent the &lt;STRONG&gt;processors&lt;/STRONG&gt;, which give attention to one thread at a time and then context switch to another thread.&amp;nbsp; The time spent running from car to car is the time required to perform a thread context switch. &lt;/P&gt;
&lt;P&gt;Now imagine that you want to maximize the throughput of this system -- the total number of cars that reach the end of their road per hour.&amp;nbsp; How do you do it?&amp;nbsp; There are some "obvious" ways to do so: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;hire more drivers (use more processors)&lt;/LI&gt;
&lt;LI&gt;eliminate some stoplights by building overpasses at intersections (eliminate critical sections)&lt;/LI&gt;
&lt;LI&gt;buy faster cars (use faster processors)&lt;/LI&gt;
&lt;LI&gt;make the roads shorter (write pages that require less code)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You'll note that each of these is either expensive or difficult.&amp;nbsp; Perf isn't easy!&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Now, I said that these are "obvious" ways to solve this problem, and those scare quotes were intentional.&amp;nbsp; Imagine a complex grid of roads with lots of stoplights, a moderate number of cars on the road, and two drivers.&amp;nbsp; It is quite unlikely that cars will spend a lot of time stopped at stoplights -- mostly they'll just breeze right on through.&amp;nbsp; But what happens when you throw another six drivers into the mix? Sure, more cars are being driven at any one time, but that means that the likelihood of congestion at stoplights just went up.&amp;nbsp;&lt;STRONG&gt;Even though there are four times as many drivers, the additional time spent at stoplights means that the perf improvement is less than a factor of four&lt;/STRONG&gt;.&amp;nbsp;We say that such systems are not &lt;EM&gt;scalable&lt;/EM&gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Or consider a moderately congested freeway system with a whole lot of cars, drivers and intersections.&amp;nbsp; Now suppose that you keep the cars, drivers and intersections the same, but you shrink the whole system down to half its previous size. You make all the roads shorter, so that instead of having eight stoplights to the mile, now you've got twenty. Does total throughput get better or worse?&amp;nbsp; In a real traffic system, that would probably make things worse, and it can in web servers as well.&amp;nbsp; The cars spend all their time at intersections waiting for a driver to run over to them. &lt;STRONG&gt;Making code faster sometimes makes performance worse because thread congestion and context switches could be the problem, not total path length. &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Similarly, making the cars faster often doesn't help.&amp;nbsp;In the real world of Seattle traffic, upgrading from my 140-or-so horsepower Miata to a 300 HP BMW isn't going to get me&amp;nbsp;home any faster.&amp;nbsp; Getting a faster processor and shorter program only helps if the "freeway" is clear of traffic. Otherwise, &lt;STRONG&gt;you sit there in your souped-up ultimate driving machine going zero at stoplights like everyone else.&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;Raw power does not scale in a world with lots of critical sections. &lt;/P&gt;
&lt;P&gt;When perf tuning servers, use the performance monitor to keep a careful eye on not just pages served per second, but on thread switches per second, processor utilization and so on.&amp;nbsp; If you cannot saturate the processor and the number of thread switches is extremely high, then what is&amp;nbsp;likely happening is that the drivers are spending way too much time running from car to car and not enough time actually driving. Clearly that's not good for perf.&amp;nbsp; Tracking down and eliminating critical sections is often the key to improving perf in these scenarios.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53411" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>Arrrrr! Cap'n Eric be learnin' about threadin' the harrrrd way</title><link>http://blogs.msdn.com/ericlippert/archive/2003/09/19/arrrrr-cap-n-eric-be-learnin-about-threadin-the-harrrrd-way.aspx</link><pubDate>Fri, 19 Sep 2003 20:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53054</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53054.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53054</wfw:commentRss><description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Arr,
        it be National Talk Like A Pirate Day.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;?xml:namespace prefix = o ns = 
"urn:schemas-microsoft-com:office:office" /&gt;Avast
        ye scurvy dogs!&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;A
        scurvy bilge rat commented on the preceding discussion about putting apartment threaded
        objects in Session scope:&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 class="commentbody"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span class="commentbody"&gt;back in the era of the NT4 Option Pack I wrote a lot of
        code that involved stashing Scripting.Dictionary objects in both session and application
        scope. [...] I forget now which version of the runtime changed the threading model
        they were registered with and broke everything for me.&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 class="commentbody"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Shiver
        me timbers!&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That be my fault.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Sorry
        about that.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;When you create an ActiveX
        object, the COM runtime code checks the registry to see if the object is marked as
        participating in the Apartment, Free or Both threading models.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;(We'll
        go into the difference between Free and Both at another time.)&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Now,
        when I was a young swabbie seven years ago I was given the task of implementing the
        Scripting.Dictionary object, and I didn't yet understand all the stuff I just told
        you maties about threading.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In one build
        that was released to the public I accidentally marked the dictionary as Both, even
        though it is an apartment object. So when lubbers would put a dictionary into Session
        scope, it would be called by multiple threads at multiple times, in violation of the
        apartment contract.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As long as there
        were only readers, it was generally OK, but as soon as there were readers and writers,
        it would usually crash and die.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;And
        of course when we corrected the mistake, all those pages went from sometimes-crashing-but-fast
        to not-crashing-but-slow. &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;That
        was my first majorly customer-impacting mistake, and probably the worst I ever personally
        made.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &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; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Speaking
        of mistakes, there was another interesting performance mistake in early releases of
        the Scripting.Dictionary object. It uses a very simple hash table for rapid lookup,
        but of course hash tables require that the hash function distribute hashes &lt;strong&gt;broadly&lt;/strong&gt; given
        a &lt;strong&gt;narrow&lt;/strong&gt; distribution of keys.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;I
        screwed up the hash algorithm, and one of the consequences was that hashing on a string
        consisting of five digits was likely to go to a very small number of hash buckets.&amp;#160;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&lt;/span&gt;&lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&amp;#160;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;We
        discovered all this the day that MSN.COM decided to store EVERY ZIP CODE IN THE UNITED
        STATES in a Scripting.Dictionary object in Session scope!&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Perf
        of MSN.COM went way south, way fast.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;The
        combination of the two mistakes above led the ASP team to write their own string table
        object, that really was Both threaded and blindingly fast. 
        &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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Arr!&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
&lt;/body&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53054" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>Why is it a bad idea to put script objects in Session scope?</title><link>http://blogs.msdn.com/ericlippert/archive/2003/09/18/why-is-it-a-bad-idea-to-put-script-objects-in-session-scope.aspx</link><pubDate>Fri, 19 Sep 2003 05:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53050</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53050</wfw:commentRss><description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;?xml:namespace 
prefix = o ns = "urn:schemas-microsoft-com:office:office" 
/&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Often
        a web site will have a series of related pages requested one after the other by the
        same user.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;As a convenience for the site
        developers, the ASP object model provides a Session object to store server-side state
        for a current user.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It also has a global
        "Application" object which stores state for an entire virtual root.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Every
        so often some ASP coder out there tries to put a JScript or VBScript object into the
        Session (or Application) object.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Things
        usually start going horribly wrong shortly thereafter -- either terrible performance
        ensues or things just break outright.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Well,
        like Groucho says, if it hurts when you do that, don't do that!&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Understanding
        why this is a bad idea will take us yet deeper into the land of threading models.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="navy" size="3"&gt;&lt;span style="FONT-SIZE: 12pt; COLOR: navy; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Marshaling 
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;I
        mentioned earlier that when you have an apartment threaded object, you need to be
        in the right apartment (thread) if you want to talk to its occupants (object instances).&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;But
        what if you are not?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;What if you are
        running some code in thread Alpha that &lt;em&gt;really&lt;/em&gt; needs to call a method on an
        object running in thread Beta?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Fortunately,
        COM provides a mechanism called &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="FONT-WEIGHT: bold; mso-bidi-font-weight: normal"&gt;cross-thread
        marshaling&lt;/span&gt;&lt;/b&gt; to achieve this.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;The
        behind-the-scenes details are not particularly important to our discussion; suffice
        to say that windows messages are involved.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        important thing to know is that when you marshal a call across threads &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="FONT-WEIGHT: bold; mso-bidi-font-weight: normal"&gt;the
        calling thread pauses until the called thread responds&lt;/span&gt;&lt;/b&gt;.&lt;span style="mso-spacerun: yes"&gt;&amp;#160;
        That seems reasonable -- after all, when you call an ordinary function you sort of
        "pause" until the function returns.&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&amp;#160;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;But
        threads are usually busy doing &lt;em&gt;something&lt;/em&gt;.&amp;#160;&amp;#160;I&lt;/span&gt;f the called
        thread is not responding to messages because it is busy doing work of its own then
        the calling thread waits, and waits, and waits...&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;To
        continue with our previous apartment threading analogy, it is rather like each apartment
        has a mailbox.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If you're in apartment
        Beta and you need someone in apartment Alpha to do something for you, you write up
        a request and hand it to the mailman who in turn sticks it in Alpha's mailslot.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Alpha's
        occupants might be busy doing work and ignoring their mail, or they may have a huge
        stack of mail to get through, or they might get right on it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;You,
        over in apartment Beta, can't do anything but wait for the mailman to deliver their
        reply.&lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
    &lt;o:p&gt;
        &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
            &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;And
            of course, even if the callee thread is completely responsive and ready to service
            your request, obviously calling across threads is orders of magnitude more expensive
            than calling in-thread.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;An in-thread
            call requires some arguments to be put on the stack and maybe stash a few values in
            registers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;A cross-thread call gets the
            operating system involved in a comparatively deep and complex way.&lt;o:p&gt;&lt;/o:p&gt;
            &lt;/span&gt;&lt;/font&gt;
        &lt;/p&gt;
        &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&amp;#160;
        &lt;/p&gt;&lt;/o:p&gt;
    &lt;/span&gt;&lt;/font&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="navy" size="3"&gt;&lt;span style="FONT-SIZE: 12pt; COLOR: navy; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Performance
        Woes&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Now
        you have enough information to figure out why putting script objects in Session scope
        is a bad idea as far as performance is concerned.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&amp;#160;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;Each
        ASP page is running on its own thread from the thread pool.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        thread that reads the object from session state will likely not be the thread that
        put the object there, but the script object is apartment threaded.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That
        means that essentially any page that accesses that session object must wait its turn
        for all other pages using that session object to finish up, because &lt;strong&gt;the marshaling
        code blocks the calling thread until the callee is available.&lt;/strong&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt; &lt;/span&gt;You
        end up with a whole lot of blocking threads, and blocking threads are not fast.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Application
        scope is even worse -- if you put a script object in Application scope then &lt;strong&gt;every
        page in the entire vroot that accesses the Application object must wait its turn&lt;/strong&gt; for
        the original thread to be free.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;You've
        effectively single-threaded your web server.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="navy" size="3"&gt;&lt;span style="FONT-SIZE: 12pt; COLOR: navy; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Script
        Engine Of The Living Dead&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;But
        it gets worse.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Remember, when the page
        is done being served up, the engine is torn down.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        compiled state remains, but the runtime state is thrown away.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;So
        suppose you have a JScript object sitting in the Session object, and the page that
        put it there was destroyed a few microseconds ago and the engine put back into the
        engine pool.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Now on another page in the
        same session you try to fetch the JScript object and call a method on it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Where's
        the runtime state associated with that object?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;It's
        gone, dude.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;When
        the script engine is torn down after the original page is served, the teardown code
        detects that there are existing objects that are owned by external callers.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The
        script engine can't destroy these objects, otherwise the caller would crash when the
        caller tried to destroy them later.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That's
        a fundamental rule of COM -- you can't destroy an object to which someone holds a
        reference.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&amp;#160;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;But
        we know that the object is going to be useless, so what we do is tell the object "the
        engine you require for life is going away.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Throw
        away everything you own and become a zombie."&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;These
        zombie objects look like script objects, but when you actually try to do something
        to them -- call a method, fetch a property, whatever -- they don't actually do anything.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They
        can't -- all the infrastructure they need to live is gone, but they can't die.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Basically
        they wander the night in ghostly torment until they are freed by whatever code is
        holding the reference.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;So
        not only are those script objects sitting in Session state wrecking your performance,
        they're not even &lt;em&gt;useful&lt;/em&gt; for anything once the original page goes away.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Incidentally,
        Windows Script Components each have their own engine which stays alive as long as
        they do, so WSC's are not affected by the zombie issue.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;They
        are still apartment threaded though.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="navy" size="3"&gt;&lt;span style="FONT-SIZE: 12pt; COLOR: navy; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Arrays
        Are Almost As Bad&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;JScript
        arrays are objects, so everything said above applies to them.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;VBScript
        arrays are not objects (more on the differences between these two kinds of arrays
        later) but even still, you shouldn't put them in Session scope either.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Though
        they do not suffer from the threading problems or the lifetime problems mentioned
        above, arrays are stored into and passed out of Session scope using our old friend
        copy-in-copy-out semantics.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;That means
        that &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="FONT-WEIGHT: bold; mso-bidi-font-weight: normal"&gt;every
        single time &lt;/span&gt;&lt;/b&gt;you index into an array in Session scope, &lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="FONT-WEIGHT: bold; mso-bidi-font-weight: normal"&gt;a
        copy of the array is made first&lt;/span&gt;&lt;/b&gt;.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;If
        that array is big, that's a big performance problem.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&amp;#160;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;Why
        do we do copy-in-copy-out?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;i style="mso-bidi-font-style: normal"&gt;&lt;span style="FONT-STYLE: italic; mso-bidi-font-style: normal"&gt;Because&lt;/span&gt;&lt;/i&gt; arrays
        are not marshaled!&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We return to the fundamental
        problem: what if two pages tried to read and write the array in the Session object
        at the same time?&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;The memory could be
        corrupted.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;We really don't have any good
        way to synchronize access to the array, so instead we simply make a complete copy
        of it every time someone tries to read or write it.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;This
        is extremely expensive, but it keeps the server heap from being corrupted.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;A
        corrupted web server heap can ruin your whole day.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;My
        advice is to not even go there.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;strong&gt;Don’t
        put information into Session scope unless you absolutely have to.&lt;/strong&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt; &lt;/span&gt;If
        you must, put in strings.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;There are lots
        of ways to store arrays or objects as strings and reconstitute them as needed.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;
        &lt;font face="Lucida Sans Unicode" color="purple" size="2"&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;/font&gt;
    &lt;/p&gt;
&lt;/body&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>How does Active Server Pages use the script engines?</title><link>http://blogs.msdn.com/ericlippert/archive/2003/09/18/how-does-active-server-pages-use-the-script-engines.aspx</link><pubDate>Fri, 19 Sep 2003 00:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53046</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53046.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53046</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;It's always struck me as a little bit odd that Active Server Pages, a web server, encourages developers to use VBScript and JScript to write server-side scripts.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;I mean, the whole point of a web server is that it produces complex strings (web pages are just strings of HTML after all) as blindingly fast as possible, on demand.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;"Blindingly fast" and "script language" do not really go together, compared to, say, C. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;My opinions -- and you'd better believe I have plenty of strong ones! -- on performance characteristics of the script engines will certainly come back in &lt;A href="http://blogs.msdn.com/ericlippert/category/2717.aspx?Show=All"&gt;future posts&lt;/A&gt;.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;But for now I want to talk a little bit about what features we added to the script engines to make them work as well as they do for ASP. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;One of the ways you make a server fast is by caching everything you possibly can cache.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;For example, suppose you need to do a job on a separate thread.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;You'd probably create a thread, do some work on the thread, and throw it away when you're done.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;OK, now suppose you need to do a million jobs but never more than, say, three at a time. Creating and destroying those million threads is potentially going to be a not-insignificant amount of the total processor time spent.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;You'd be better off &lt;B&gt;&lt;SPAN&gt;creating three threads and re-using them as necessary&lt;/SPAN&gt;&lt;/B&gt;. &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This strategy is called &amp;#8220;thread pooling&amp;#8221;, and ASP certainly uses it.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;(UPDATE: I've written a follow-up article on &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/02/15/73366.aspx"&gt;Thread Happiness Disease&lt;/A&gt;.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;ASP caches a lot more than that though.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;It also pools script engines and caches compiled state.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Let me explain with an example. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose a request comes in for this page, time.asp:&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Times New Roman" size=3&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;lt;html&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399&gt;&lt;SPAN&gt; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;lt;% Response.write Now() %&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399&gt;&lt;SPAN&gt; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;&amp;lt;/html&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399&gt;&lt;SPAN&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose further that this is the first-ever request for this page since the server was started.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The thing above isn&amp;#8217;t a legal script, so ASP parses out the non-script blocks and stores them in the Response object.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;It then generates a real script that looks something like 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;Response.WriteBlock 0&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399&gt;&lt;SPAN&gt; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;Response.Write Now()&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399&gt;&lt;SPAN&gt; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;Response.WriteBlock 1&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;ASP also has a pool of created-but-not-initialized script engines sitting around.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;I said in my last post that &lt;STRONG&gt;when the script engines are not initialized they can be called on any thread,&lt;/STRONG&gt; so it does not matter that these engines were not created on whatever thread happened to be pulled out of the thread pool.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;ASP initializes the engine on the current thread and passes in the script code above.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The script engine compiles the script, runs it, and the ASP object model sends the resulting string off to the client. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The script engine then gets uninitialized, but does not throw away its compiled state.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The compiled state &amp;#8211; the proprietary bytecode form of the language &amp;#8211; is maintained in memory because the second time someone asks for that page, ASP do not want to have to go through all the time and expense of translating the page to script and compiling the script to bytecode. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The thread and the now-uninitialized engine go back to their respective pools. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now suppose a second request comes in for time.asp.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This time ASP pulls a thread out of the thread pool, notices that it has an engine with the compiled state just sitting there, attaches the engine to the thread, and runs the script again.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;No time is spent creating the thread, creating the script engine, translating the page to code or compiling the script to bytecode. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose further that in the few milliseconds that ASP is running this script, a third request comes in for this page.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Then what happens?&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;There are two obvious possibilities: 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;1)&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Wait for the current engine to finish, and start it right back up again when it is done.&lt;SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;2)&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Fetch a new engine from the engine pool and start over &amp;#8211; translate the page to script, compile, run. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The trouble is, both of those are potentially slow.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The first in particular could be extremely slow. We needed a third option. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In my previous post I discussed &lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx"&gt;the sorts of trouble you can get into with multi-threading&lt;/A&gt;.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Note that the problem I described happens because two threads tried to both read &lt;I&gt;&lt;SPAN&gt;and&lt;/SPAN&gt;&lt;/I&gt; write a particular value.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;If the value was read-only, then obviously there would not have been a problem.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;You can read a read-only value from as many threads as you want! 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Hey, once the script engine compiles a script into bytecode, that bytecode is read-only.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;It&amp;#8217;s never going to change again.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This means that two script engines on two different threads can share bytecode! 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I lied earlier when I said that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;InterruptScriptThread&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; was the only exception to our weird threading model.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;We have another exception &amp;#8211; at any time, you can call &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; from any thread.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This takes an existing script engine and gives you a new script engine with exactly the same compiled state, but able to run on a different thread. Each engine maintains its own runtime state &amp;#8211; variable values, etc &amp;#8211; but the compiled state is shared. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;So in this scenario, ASP &lt;B&gt;&lt;SPAN&gt;clones the running engine onto another thread and then runs the new engine concurrently&lt;/SPAN&gt;&lt;/B&gt;.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This is&amp;nbsp;&lt;EM&gt;somewhat&lt;/EM&gt; expensive &amp;#8211; it has to create a new engine, after all &amp;#8211; but is &lt;EM&gt;much cheaper&lt;/EM&gt; than compiling up all that state again. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Of course, ASP is much more complicated than that quick sketch.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;What I&amp;#8217;m getting at here is that there actually is some rhyme and reason to our bizarre-seeming choices of threading model.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;The script engine design was driven by the need to solve a very specific set of very disparate problems.&amp;nbsp; Without knowing what the problems were, the resulting design looks kind of random.&amp;nbsp; But once you know the history, well, I guess it looks a little &lt;EM&gt;less&lt;/EM&gt; random.&lt;/SPAN&gt;&lt;/FONT&gt; &lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;UPDATEL: I've written&amp;nbsp;a follow-up article on &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/02/19/76438.aspx"&gt;how the ASP compilation model is affected by having&amp;nbsp;multiple languages per page&lt;/A&gt;.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53046" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item><item><title>What are &amp;quot;threading models&amp;quot;, and what threading model do the script engines use?</title><link>http://blogs.msdn.com/ericlippert/archive/2003/09/18/what-are-threading-models-and-what-threading-model-do-the-script-engines-use.aspx</link><pubDate>Fri, 19 Sep 2003 00:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53041</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53041.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53041</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;I've got a few ideas for some future posts that depend on the reader understanding a little bit about COM threading.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since I myself understand only a little bit about COM threading, I'll just do a brain dump for you all right here.&lt;o:p&gt;&lt;/o:p&gt; &lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;I'm sure you all know about multi-threaded applications.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The idea is that the operating system switches back and forth between threads within a process using a scheduling algorithm of some sort.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When a thread is "frozen" all the context for that thread -- basically, the values of the registers in the processor -- is saved, and when it is "thawed" the state is restored and the thread continues like it was never interrupted.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;That works great right up to the point where two threads try to access the same memory at the same time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Consider, for example, the standard implementation of &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;IUnknown::Release&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;ULONG MyClass::Release()&lt;BR&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;--this-&amp;gt;m_cRef;&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;if (this-&amp;gt;m_cRef == 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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;delete this;&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return 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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;return this-&amp;gt;m_cRef;&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: #333399; FONT-FAMILY: 'Lucida Console'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Now suppose the ref count is two and two threads try to each do a single release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That should work just fine, right?&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Wrong.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The problem is that though &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;--this-&amp;gt;m_cRef &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;looks like a single "atomic" operation, the compiler actually spits out code that acts something vaguely like this pseudo-code:&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;// "this" is stored in Register1&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;1 copy &lt;EM&gt;address&lt;/EM&gt; of "m_cRef" field of pointer stored in Register1 to Register2&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;2 copy &lt;EM&gt;contents&lt;/EM&gt; of address stored in Register2 to Register3&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;3 decrease contents of Register3 by one&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;4 copy &lt;EM&gt;contents&lt;/EM&gt; of Register3 back to &lt;EM&gt;address&lt;/EM&gt; stored in Register2&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;5 compare contents of Register3 to zero, store Boolean result of comparison in Register4&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;6 if Register4 is false then return contents of Register3&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;7 ... etc -- do deletion, return zero&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Notice that the compiler can be smart and re-use the contents of Register3 instead of fetching &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;this-&amp;gt;m_cRef&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; three times.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The compiler knows that no one has changed it since the decrease.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;So suppose we have a red thread and a blue thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each has their own registers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Suppose the processor schedules them in this order:&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;1 copy address of "m_cRef" field of Register1 to Register2&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;2 copy contents of address stored in Register2 to Register3&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: #333399; FONT-FAMILY: 'Lucida Console'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;CONTEXT SWITCH! Save &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Register1 = this, Register2 = &amp;amp;m_cRef, Register3 = 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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&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: red; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;1 copy address of "m_cRef" field of Register 1 to Register 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; COLOR: red; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;2 copy contents of address stored in Register 2 to Register 3&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: #333399; FONT-FAMILY: 'Lucida Console'"&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: red; FONT-FAMILY: 'Lucida Console'"&gt;CONTEXT SWITCH! Save &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Register1 = this, Register2 = &amp;amp;m_cRef, Register3 = 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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;CONTEXT SWITCH! Restore Register1 = this, Register2 = &amp;amp;m_cRef, Register3 = 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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;3 decrease contents of Register3 by one&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;4 copy contents of Register3 to address stored in Register2&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;5 compare contents of Register3 to zero, store Boolean result of comparison in Register4&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;6 if Register4 is false then return contents of Register3&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: #333399; FONT-FAMILY: 'Lucida Console'"&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: #333399; FONT-FAMILY: 'Lucida Console'"&gt;Register 4 is false because Register3 = 1, so this returns 1.&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: #333399; FONT-FAMILY: 'Lucida Console'"&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: red; FONT-FAMILY: 'Lucida Console'"&gt;CONTEXT SWITCH! Restore Register1 = this, Register2 = &amp;amp;m_cRef, Register3 = 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; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;And now you see where this is going, I'm sure.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Because the original value was stored in the red thread before the blue thread decremented it, we've lost a decrement&lt;/B&gt;. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;Both threads will return 1.&amp;nbsp;T&lt;/SPAN&gt;his object's ref count will never go to zero, and its memory will leak.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A similar problem plagues &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;AddRef&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; -- you can lose increment operations, which causes memory to be freed too soon.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;How do we solve this problem?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Basically there are two ways to do it: &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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-fareast-font-family: 'Lucida Sans Unicode'"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Do the necessary work to ensure thread safety&lt;o:p&gt;&lt;/o:p&gt; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-fareast-font-family: 'Lucida Sans Unicode'"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Require your callers to behave in a manner such that you never get into this situation in the first place.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;The operating system provides tools to make multi-threaded programming work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are methods like &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;InterlockedIncrement&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;, which really do "atomically" bump up a counter. Signals and semaphores and critical sections and all the other tools you need to make multi-threaded programs are available. I'm not going to talk much about those. &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Writing a truly free-threaded program is a lot of work.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are a lot of ways to get it wrong, and there are potential performance pitfalls as well.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Fortunately, there is a middle ground between "only one thread allowed" and "any thread can call any method at any time".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;The idea of the COM threading models is to provide a &lt;B style="mso-bidi-font-weight: normal"&gt;contract&lt;/B&gt; between callers and callees so that, as long as both sides follow the contract, situations like the one above never come to pass.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Suppose a caller has several instances of an object (the callee), and the caller has several threads going.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The commonly used standard threading contracts are as follows:&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* &lt;B style="mso-bidi-font-weight: normal"&gt;Single threaded&lt;/B&gt; -- all calls to all instances of the object must always be on the same thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are no synchronization issues because there is always only one thread no matter how many object instances there are.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The &lt;B style="mso-bidi-font-weight: normal"&gt;caller&lt;/B&gt; is responsible for ensuring that &lt;B style="mso-bidi-font-weight: normal"&gt;all calls to all instances are on the same thread&lt;/B&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* &lt;B style="mso-bidi-font-weight: normal"&gt;Free threaded&lt;/B&gt; -- calls to the object can be on &lt;B style="mso-bidi-font-weight: normal"&gt;any thread&lt;/B&gt; at &lt;B style="mso-bidi-font-weight: normal"&gt;any time&lt;/B&gt;, including multiple threads at the same time.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The &lt;B style="mso-bidi-font-weight: normal"&gt;object&lt;/B&gt; is responsible for &lt;B style="mso-bidi-font-weight: normal"&gt;all synchronization issues&lt;/B&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* &lt;B style="mso-bidi-font-weight: normal"&gt;Apartment threaded&lt;/B&gt; -- all calls to any &lt;B style="mso-bidi-font-weight: normal"&gt;given instance&lt;/B&gt; of the object must always be on the same thread, but &lt;B style="mso-bidi-font-weight: normal"&gt;different instances can be called on different threads at the same time&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The &lt;B style="mso-bidi-font-weight: normal"&gt;caller&lt;/B&gt; is responsible for ensuring that &lt;B style="mso-bidi-font-weight: normal"&gt;given an instance, all calls to that instance happen on the same thread&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The &lt;B style="mso-bidi-font-weight: normal"&gt;object&lt;/B&gt; is responsible for synchronizing access to global (that is, not-per-instance) data that it owns.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;An analogy might help. Think of an apartment building where each apartment is a thread and each person is an object instance.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You can put as many people into one apartment as you want, and you can put people into lots of different apartments, but once you've done so, &lt;B style="mso-bidi-font-weight: normal"&gt;you always have to go to a person's apartment if you want to talk to them&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;Why? Because they never move out once they're in an apartment, you have to wait for them to die before they ever leave.&amp;nbsp; (Insert New Yorker joke here.)&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;Furthermore, you can't talk "through the walls" from one apartment to someone in another apartment.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; (Well, actually you can -- that's called "marshaling", and that's a subject for a future post.)&amp;nbsp; And finally, i&lt;/SPAN&gt;f the people jointly own a shared resource -- say, a rooftop barbecue, to stretch this silly analogy to its limit -- then they must sort out amongst themselves how to synchronize access to the shared resource.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* &lt;B style="mso-bidi-font-weight: normal"&gt;Rental threaded&lt;/B&gt; -- calls to an object can be on &lt;B style="mso-bidi-font-weight: normal"&gt;any thread &lt;/B&gt;but the &lt;B style="mso-bidi-font-weight: normal"&gt;caller guarantees that only one thread is calling into the object at any time&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Rental threading requires a different analogy: suppose the object instances are&amp;nbsp;rented televisions and again&amp;nbsp; threads are apartments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; A television can be moved from apartment to apartment but can never be in more than one apartment at the same time.&amp;nbsp;Multiple televisions can be in the same apartment, and multiple apartments can have multiple televisions.&amp;nbsp; &lt;STRONG&gt;But if you want to watch a television, you have to go to the apartment where it is.&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Whew, that was a long preamble.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;How does this pertain to the script engines?&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Most COM objects -- almost all ActiveX objects, and all of the object models commonly used by script -- are apartment threaded objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;They expect that multiple instances of the object can be created on multiple threads, but once an instance is created on a thread, it will always be called on that thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This gives us the best of both worlds -- the caller can be free threaded and can create multiple objects on multiple threads, but the callee does not have to synchronize access to any per-instance data.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;But the script engines are free threaded objects. &lt;B style="mso-bidi-font-weight: normal"&gt;The script engines must ensure that they do not violate the apartment model contract.&lt;/B&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&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; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;So guess what?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The script engines actually have a bizarre, custom contract that is a little more restrictive than free threading and less restrictive than apartment threading!&lt;SPAN style="mso-spacerun: yes"&gt;&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; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;The script engine contract is as follows:&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* When the script engine is in a state where it cannot possibly call an ActiveX object -- for instance, if it has just been created and has not started running code, or if it is just about to be shut down -- then the script engine really is free threaded, but who cares? &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;It can't do much in this state.&lt;/SPAN&gt; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* When the script engine is initialized -- when the script engine host has started the process of passing code and object model state to the engine -- the script engine morphs into an apartment threaded object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All calls to the script engine must be on the initializing thread until the script engine is shut down again.&lt;/SPAN&gt; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* There&amp;nbsp;are two exceptions to the previous rule -- the &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;InterruptScriptThread &lt;FONT face="Lucida Sans Unicode" color=#800080&gt;and &lt;/FONT&gt;Clone&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; methods can always be called from any thread.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The former is the mechanism whereby the&amp;nbsp;host can signal a long-running script that it is taking too long and needs to shut down.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Obviously that has to be on a different thread than the one that is taking too long! The latter is&amp;nbsp;how ASP starts a second&amp;nbsp;request for a currently-executing page to run on a second thread without recompiling the script.&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp; &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;* If the script host (the browser, for instance) violates this contract, the script engine will usually return the E_UNEXPECTED error, which has the helpful error message "CATASTROPHIC FAILURE".&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(Not that we're trying to scare you or anything; it's just our way of saying "please don't do that".)&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Anyway, that was a whole lot of not particularly germane information unless you are developing your own script host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But like I said, I have a few ideas for some future topics that will assume some background understanding of COM threading models.&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: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt; &lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53041" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category></item></channel></rss>