Thunderclap, the newsletter of Rolling Thunder Computing
Volume 1, Number 3 Spring 1998
In this issue:
About Thunderclap
Subscription Information
Feature Article: Inherit Synchronization for Scalability in
COM+
New Book on COM+ by David Platt,
published by Microsoft Press, Free Beer at Release Party
Blatant Self Promotion
Contest with Prizes: Computer Haiku
Results of Last Contest: Famous Last Words
This is the third issue of my (more or less) quarterly newsletters. Each will bring you a technical article on COM development, which I hope you will find useful. Each will also bring you a contest, allowing you to show off your intelligence and creativity to win prizes, which I hope you will find funny. In between you will find my own blatant self promotional material, telling you about the latest ways I've come up with to separate you from your money. (I could have said "carefully selected products and services that we feel might interest you", or other mealy-mouthed horsepuckey. You want the truth or you want me to waste my time and yours dressing it up?)
I'd like to hear what you think about this newsletter and what types of articles you'd like to see in the future. Would you prefer technical programming articles, such as the one in this current issue? Future topics on this track might be, "What the Heck Is the Free-Threaded Marshaler, Anyway?" or "Our Friend, the Causality ID". Or would you prefer higher-level conceptual articles, like "With All the Fuss About COM+, What's In It For Me Today?" Send your e-mail comments to newsletter@rollthunder.com.
This newsletter may be freely redistributed, provided that it is sent in its entirety. If you enjoyed it, can I ask you to please forward it to a friend who might also enjoy it? The subscription roll has grown from nowhere to over 600 for this issue.
Thunderclap is free, and is distributed via e-mail only. We never rent, sell or give away our mailing list. Subscription and unsubscription are handled by a human operator reading e-mail messages. To subscribe or unsubscribe, jump to the Rolling Thunder Web site and fill in the subscription form.
When we use COM to write middleware components for enterprise applications, we care about scalability in a way that we didn't when we wrote COM components for the desktop. A desktop COM server might have one or two or three clients. An enterprise COM server could easily have hundreds. Writing COM objects that can successfully execute in such an environment requires a change of programming mindset.
The most deadly foe of scalability is a bottleneck, as anyone knows who commutes on the lower deck of Boston's Central Artery. A ten-mile, ten-minute ride from Rte. 128 to the lower deck doesn't matter much if it takes you an hour to get through the last mile, and it does. Anyone remember (dating myself here) the 64 kByte user heap in 16-bit Windows? Or 640k MS-DOS? You could stuff more RAM chips into your machine until you needed a liquid sodium cooling system, but your programs couldn't use it due to limitations of the operating system architecture. These bottlenecks held up the entire industry until a new architecture erased them (and replaced them with its own, but that's another story).
Writing COM components that live in single-threaded apartments (STAs, marked as ThreadingModel=Apartment in the registry) present just such a bottleneck. (In my previous articles, I described these components as as "using the apartment threading model". I have to switch nomenclatures now to accurately explain the new neutral apartment in COM+, which you can read about in my new book or perhaps a later issue of this newsletter. All things must pass) An STA component receives all of its calls on the same thread every time. An object of this type is said to have thread affinity. This is fine for user interface COM components such as ActiveX controls; since they deal with windows (the user interface element, not the operating system), they're going to be thread-centric anyway. But thread affinity can cause deadly bottlenecks on a distributed enterprise system. An incoming call from a remote client is received on a thread from a pool that exists for this purpose. A call destined for an object that lives in the process's lone multi-threaded apartment (MTA, marked as ThreadingModel=Free in the registry), or in COM+'s new neutral apartment (NA, ThreadingModel=Neutral in the registry) can be made directly from this receiving thread. However, an incoming call destined for an STA object must be marshaled via the Windows message queuing mechanism to the thread that owns the STA in which the object resides. This burns a lot of microseconds that you'd prefer to use for your business process instead of wasting them on this anal-retentive infrastructural nonsense -- bad enough, but that's not the worst. The killer problem is that if the object's STA thread is blocked, waiting for an external event such as a database access or a file read, the incoming call has to wait until the thread clears the block, it can't bypass the block by proceeding on another thread. You have a hellish bottleneck. Worse yet, if the call can't proceed on a different thread, your server program can't make use of other CPU chips in the machine. If you spend a gazillion dollars on a fancy server with 8 CPUs but have all your objects created on the same thread, one chip does all the work while the other 7 act as very expensive room heaters (which then require expensive air conditioners). Not smart.
If we didn't care about thread-centric user interface elements, which in middleware we don't, why would we ever write STA components? Because, since all their calls arrive on the same thread, STA components don't require synchronization code to protect them against concurrent access from different threads. Anyone who has ever used a chain saw understand the hazards of being disturbed at the wrong moment. Similarly, an object can cause untold damage if an unruly thread joggles its elbow while the object performs delicate operations on a different thread. If we put our components not in an STA, but rather in the process's lone MTA or NA, then the object can receive calls from multiple threads at the same time. This means that we have to write our own synchronization code to protect critical operations, essentially erecting a fence around ourselves so no one can bother us while we're making a cut with the chainsaw. This doesn't sound all that bad, but as we saw in the last issue of ThunderClap, it is extremely difficult to get it right for all callers in all cases, essentially impossible in a distributed system. It takes a lot of time and costs a lot of money to develop non-revenue infrastructural code that A) is the same for most distributed operations, so you're re-inventing the wheel and B) doesn't work very well, so your customers aren't happy. We want to get rid of thread affinity and its resulting bottlenecks, but the price of writing our own synchronization code is extremely high. We'd love it if this problem just went away.
This is a generic problem, and we'd really like a generic solution to it. We'd really like someone to abstract the problem away for us, as has, for example, the Java language. Java requires us to add only a single keyword, "synchronized" to the method definition in our source code like this:
public synchronized void SayHello ( )
{
MessageBox (0, HelloMessage, "jhellodll", 0) ;
}
The Java Virtual Machine (JVM) will make sure that only one thread can call the specified method at a time. That's fine if you are going to write all of your COM code in Java, but no one is doing that today. Microsoft and Sun's legal wrangles have stunted the growth of this language in the Windows environment more surely than mere hostility from Microsoft ever could. No one really wants to use a language that some idiot lawyer might declare illegal on some future date, no doubt the day before you were to ship your product. Managers get screaming nightmares of police raids with drawn guns and German Shepherds trained to ignore dope but sniff out the scent of a VJ6 CD-ROM. Even the thought of an civilized audit that might uncover the pornographic movies they've been downloading on the company T1 line fills them with dread. Rumors in the trade press speculate that Microsoft might drop Java support, possibly replacing it with a language called "Cool". Plus Java components execute slowly due to the additional layer of abstraction provided by the JVM. Not many developers will make this switch any time soon.
What we'd really like is some way to implement that same idea for any COM component, not just one written in Java. We'd like synchronization code, similar to what the JVM uses when it sees that keyword, to become part of the operating system, available on a binary basis. We want Microsoft to add a generic synchronization service to the operating system. And that's exactly what they've done in COM+, which is an integrated part of Windows 2000.
As I say in my book, COM+ provides prefabricated infrastructural services for operations that are common to many enterprise apps. One such piece is synchronization. (The others, as discussed in my new book, are security, transactions, queued components, events, in-memory database, and load balancing). In COM+, you write your business logic in the form of components, which are COM classes packaged in in-proc servers, using your favorite tools such as VB or the ATL, just as you've been doing for the last five years. You then use administrative tools to tell COM+ the services that you want COM+ to wrap around these components when a client uses them. COM+ then places itself between the client and object, intercepting the calls from the former and performing its services before delivering them to the latter. If you think of a standard COM proxy and a stub, but with a lot more brains, you'll have about the right mental model.
I've prepared a sample program that demonstrates the synchronization services provided by COM+. This program will (OK, should) work on the Beta 3 version or later of any flavor (Professional, Server, etc.) of Windows 2000. You can click here to download the code. It consists of a simple MTA (ThreadingModel=Free) component that I wrote using the ATL, and a multithreaded client program that I wrote using the MFC.
After unzipping the code, the first thing you need to do is to install the component into the COM+ runtime environment. You do this by using the Component Services snap-in (aka the COM+ Explorer), found on the "Administrative Tools" menu of your W2K Start button. Expand the snap-in's left-hand tree until you see the "Applications" folder. Left-click on it to select it, then right-click on it and choose "New -- Application". Follow the Wizard steps to create a new empty application, accepting the Wizard's default options. You should see your new application appear in the tree. An application is the basic unit of administration in COM+. In MTS, they were known as "Packages", which I thought was a more descriptive term. We need an application to hold our component, but it is not otherwise interesting in this example.
Expand your new application until you see its "Components" folder. Left-click on this to select it, then right-click on it and choose "New -- Component". Follow the Wizard's instructions to add a new component (not one that is already registered). Use the file selection dialog box to select the file containing the sample component, "RTSynchDemo.dll", which came with your download. Your Component Services snap-in will look something like this:
Now right-click on your new component, select "Properties", then select the "Concurrency" tab from the property sheet. Your property page will look something like this:
The "Required" button should already be selected; if not, select it and click OK.
When you use the Component Services snap-in, you are making entries in the COM+ Catalog. This is a new system database that contains the administrative information that tells COM+ which services to provide for an application and component. There's so much new administrative information that they couldn't fit it into the existing registry. If you think of the COM+ Catalog as the registry on steroids, you will have about the right mental model. Reading and writing the data in the catalog is not restricted to human users of the snap-in; system-provided objects make it accessible to programs as well.
Now that your component is properly installed and configured, run your client app, called "mfcclient.exe". It will look like this:
Click the "Create" button. The client does exactly what it did in classic COM; it simply calls CoCreateInstance (CreateObject for you VB non-geeks) specifying the CLSID (VB:ProgID) of the sample component. The object pointer is stored as a global variable in the client app. The client doesn't know, or need to know, or especially want to know anything about COM+ applications or synchronization. It just uses COM the way it always has. The creation process may take longer than you are used to because launching the app requires more thinking on the part of the operating system, as shown below.
The SCM in Windows 2000 has gotten smarter. Whereas before it simply looked in the registry, found and launched the server, created an object from the server's class factory and set up a proxy/stub pair if necessary, now it does a lot more than that. Instead of the registry, it the SCM looks in the COM+catalog and finds the specified component. It looks at the application to which the component belongs, sees that it is configured to run in a spearate address space, and launches the utility program "dllhost.exe" to host the component. It then creates a new object using the same class factory as always. It then checks the component's administrative properties that you made in the catalog, such as whether or not it requires synchronization. Using these settings, sometimes called metadata, the SCM sets up policy objects that perform interception and provide COM+ services. These policy objects are positioned between the client and the channel, and between the channel and the stub, as shown below:
When a call goes from the proxy to the channel, the client's policy objects are executed. When a call goes from the channel to the stub, the server's policy objects are executed. In the synchronization case shown here, a server policy object would check to see if the incoming call was part of the same activity, the same logical call stack. If not, it would wait on a mutex that the policy created when it was first set up. If the mutex was unowned, the call would proceed directly to the object. If not, if some other thread was already in a call to the object, it would block. When the call returns from the stub, the policy object would release the mutex. (Note: Real geeks always ask at this point where the spec for a policy object can be found and how can they write one to implement their own interception logic. The spec hasn't been released for COM+ version 1 and probably won't be until version 2 or later. I think Microsoft wants to reserve the right to make changes to the policy architecture based on what they learn from version 1).
To demonstrate this functionality, click the "Call from Thread A" button in your client app. Internally the client app will pass the request from the UI thread to a worker thread that it keeps around for this purpose. The worker thread will make the call to the object. You will see a dialog box, saying "Hello". Do not dismiss it; leave it up so the COM call doesn't return. Now click the "Call from Thread B". The UI posts the message to a different worker thread, which makes the COM call as the first one did. However, you don't see a second message box. That's because thread B's call is blocked at the policy object. When you click OK to get rid of the first message box, you will immediately see the second one. Neither client nor server wrote any synchronization code. We've inherited the synchronization from the COM+ runtime environment, simply by making administrative entries saying that we wanted it. (Note: The word "inherit" strikes a deep emotional chord in object oriented programmers. I am using it here in its most generic sense, of something valuable dumped in your lap in return for no effort on your part, which you don't deserve and will probably squander. I'm not using it in the rigorous OO sense of the word.)
To demonstrate that this synchronization service is provided by COM+ and controlled by our catalog entries, let's turn it off. Either click "Release" or close the client app. Now you need to shut down the server. It has a system-configured timeout interval that defaults to 3 minutes. Either wait this long, or right-click on your application in the snap-in and choose "Shut Down" from the context menu. Now bring up the component's property page as before. You probably noticed that some of the choices in the picture above were grayed out. That's because choices made elsewhere in COM+ preclude it. Choose the "Activation" tab and clear the "Enable Just In Time Activation" check box. Now go back to the "Concurrency" tab and click the radio button that says "Not Supported". Click OK, then run the test again. You will see both message boxes appear immediately after you click the client button, because COM+ is no longer performing the synchronization service. Again, we didn't write any code to make it happen.
Since this is the synchronization service that everyone will use, Microsoft could afford to spend a lot of time and money on getting it just right (or just how they think it ought to be, which isn't necessarily the same thing). For example, the COM+ synchronization service uses our friend the Causality ID (you KNOW I was going to work that into one of these issues), essentially a logical call stack ID that remains the same even when a call switches physical threads when passing through a proxy and stub, to ensure that the reentrancy problem that I wrote about last time is properly handled. It's a better service than you could afford to write yourself, because they have many, MANY more units over which to amortize the cost.
I realize that this is just a skim of the surface, probably raising as many questions as it answers. That's by design. If you want the rest of the answers, the next section of this newsletter will tell you where to buy them. Think of this article as a free sample of cigarettes.
Good luck with it. As Red Green would say, until next time, "Keep your stick on the ice."
by David S. Platt, President of Rolling Thunder Computing
Published by Microsoft Press
Free Beer at the Release Party 6/14 in Cambridge MA!
It's been a long haul, but I finally finished my book on COM+. It's entitled Understanding COM+, published by Microsoft Press, ISBN 0-73560-666-8. It's a different approach than my other books, more of a conceptual overview than a wealth of cut-and-paste code. I'm using the same format that David Chappell did in his very successful Understanding ActiveX and OLE, published by Microsoft Press in 1996.
The book has been released to manufacturing, the presses are rolling as I write these words, and it ought to be on shelves by June 14. We're planning a book release party for 5:00 that day at Quantum Books, 4 Cambridge Center, Cambridge MA, featuring microbrew beer from the Cambridge Brewing Company. Come on by, hoist a beer, and pick up a copy (ideally, buying it rather than putting it down), either autographed or undamaged. If you're coming from afar, I'd suggest calling Quantum first to make sure that the books actually did arrive from the bindery.
The table of contents of Understanding COM+ is:
1. Introduction to COM+ |
2. COM+ Architecture |
3. Transactions |
4. Queued Components |
5. Events |
6. In-Memory Database |
7. Load Balancing |
New In-House Training Class on COM+
Rolling Thunder Computing is pleased to announce its new in-house training class on COM+. This three or four day training class will cover all the portions of COM+, including that catalog, security , synchronization and threading, transactions, queued components, events, in-memory database, and load balancing. You can read all about it on Rolling Thunder Computing's web site, http://www.rollthunder.com.
David Platt is Byte Magazine's Newest Columnist
Remember Byte magazine? Most geeks that I know have fond memories of it from the early days of microcomputing, as do I. Most people know that it ceased publication a while back. But not many people seem to know that it's been resurrected on the Web, at http://www.byte.com. And fewer still seem to know that it features yours truly as the new ActiveX/COM columnist. My first article was entitled "What the Heck is ActiveX, Anyway?".
OLE for Life Insurance in New York in March
I'll be teaching the next public class on OLE for Life Insurance in August, probably in Pasadena CA. The exact dates are still under negotiation. Consult http://www.acord.com for a syllabus, registration, and the exact dates and location.
ActiveX for Health Care
We've been so busy with COM+ that we're not going to run a public class on AHC until next winter. But if you'd like it in-house at your company, we'd be more than happy to bring it to you. For more information, see http://www.rollthunder.com/ahc.htm.
New Contest with Prizes: Computer Haiku
This contest lets you show off your skill in writing computer-related haiku. Haiku is a Japanese form of poetry whose verses are three lines long, having 5, 7, and 5 syllables. They generally do not rhyme, though you can certainly submit one that does if you want. Here's an example, written jointly by myself and Charles Parker of Microsoft. You can see a bit of Canadian influence in the last line, probably because I had just finished a gig in Canada when I wrote it.My cat pressed "Reset".
Now she's a tennis racket.
No more furballs, eh?
I find that haiku grows on me. Once I'm thinking about them, they pop out of my subconscious a line at a time. I'll hear a phrase or think it, then say to myself, "Wow, that would be a great haiku line." Like, "stupid programmers," an excellent 5 syllable opening or closing line. Or, "should be taken out and shot,", an excellent middle line. Sometimes I'll think of a line that sounds cool but doesn't quite fit, like the 6-syllable "slowly and painfully". With a little editing, it could fit in either position, say, "slowly, painfully" for an opening or closing, or "slowly and quite painfully" for the middle. Start thinking now, and you'll be surprised how they'll pop out. Or have a brainstorming session with a few friends and a few six-packs. You'll find they just keep on coming. Like:
Besides the racket
She made a nice fur hat and
Three or four tacos.
Your entries must be computer-related and original. This isn't a family newsletter, so they don't have to be clean or politically correct. Submitting more than one increases your chances of winning. There are many haiku sites on the Internet. While they may get your juices flowing, please do not submit any haiku that you have not written yourself. First prize is $100, second prize $50. Winners will be announced in the next issue of Thunderclap, and the judge's decision (mine) is final. In the event of duplicate or similar entries, the earliest wins. All entries become property of Rolling Thunder Computing. All authors will be identified by first and last names, but not by company. Authors names will be withheld if you so request. Submit your entries via e-mail to contest@rollthunder.com.
Results of Last Contest: Famous Last Words
Here are the results of the second contest, in which you were asked to supply the last words of a famous person, living or dead, real or fictional:.
The first prize winner, $100:
David S. Platt: "Don't get me started." (Mr. Platt uttered this phrase only
moments before a jolt of electricity from his laptop stopped his heart. As a result,
onlookers, including two paramedics, took this to mean he did not wish to be
resuscitated.)
Bob Dolan
The second prize winner, $50
Red Green: "How much did ya say them American TV guys make?!"The next season
the show is cancelled after Red introduces a mindless wife, three bratty kids and an 18
year old "Tool Time" hardware model.
Ted Herron
Honorable mention to all:
Rene Descartes: "I thought therefore I was"
John Holmes: "I feel like I've got 12 inches in the grave already"
Bill Gates: "A fatal error has occurred in my application"
Doug Fulford
Edward Kennedy to Mary Jo Kopechne : "What if you get pregnant - we'll cross that
bridge when we come to it ..."
Melfyn Lloyd.
Hillary Clinton: "Bill, I hired a new intern for you. Her name is Lorena
Bobbitt."
Annette Mackail
Eugene Robinson: "$40 bucks same as in town"
Keith Schwols
Prince Charles : "It's true, Camilla, I'm going to Di "
Mickey Mouse : "Dis knee is going to be the death of me"
Larry Flynt : "Hello Saint Peter, Jerry Fartwell sent me"
Kit Ng
Legal Notices
Thunderclap does not accept advertising; nor do we sell, rent, or give away our subscriber list. We will make every effort to keep the names of subscribers private; however, if served with a court order, we will sing like a whole flock of canaries. If this bothers you, don't subscribe.
Source code and binaries supplied via this newsletter are provided "as-is", with no warranty of functionality, reliability or suitability for any purpose.
This newsletter is Copyright © 1999 by Rolling Thunder Computing, Inc., Ipswich MA. It may be freely redistributed provided that it is redistributed in its entirety, and that absolutely no changes are made in any way, including the removal of these legal notices.
Thunderclap is a registered trademark ® of Rolling Thunder Computing, Inc., Ipswich MA. All other trademarks are owned by their respective companies.