<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!-- saved from url=(0098)http://devnet.developerpipeline.com/documents/s=9843/q=1/cuj0512alexandrescu/0512alexandrescu.html --> <HTML><HEAD><TITLE>Developer::Pipelines | Policy-Based Memory Allocation</TITLE> <META http-equiv=Content-Type content="text/html; charset=iso-8859-1"> <META content=NOARCHIVE name=GOOGLEBOT> <META http-equiv=Description content="The way your application allocates memory can have a dramatic effect on its performance. Modern general-purpose memory allocators are pretty efficient, but there's always room for improvement."><LINK rev=Stylesheet href="heaplayers-article-cuj_files/pipelines_fonts.css" type=text/css rel=Stylesheet><LINK rev=Stylesheet href="heaplayers-article-cuj_files/pipelines_layout.css" type=text/css rel=Stylesheet><LINK rev=Stylesheet href="heaplayers-article-cuj_files/shared.css" rel=Stylesheet><LINK rev=Stylesheet href="heaplayers-article-cuj_files/topics.css" rel=Stylesheet> <SCRIPT language=JavaScript1.2 src="heaplayers-article-cuj_files/stm31.js" type=text/javascript></SCRIPT> <!-- pop up openscript --> <SCRIPT type=text/javascript> function openScript(url, width, height) { var Win = window.open(url,"openScript",'width=' + width + ',height=' + height + ',resizable=1,scrollbars=yes,menubar=yes,status=yes' ); } </SCRIPT> <META content="MSHTML 6.00.2900.2802" name=GENERATOR></HEAD> <BODY vLink=#003366 link=#003366 bgColor=#ffffff leftMargin=0 topMargin=0 marginheight="0" marginwidth="0"><!-- SiteCatalyst code version: G.7.Copyright 1997-2004 Omniture, Inc. More info available athttp://www.omniture.com --> <SCRIPT language=JavaScript><!--/* You may give each page an identifying name, server, and channel onthe next lines. */ var s_pageName="http://devnet.developerpipeline.com/cpp/cuj0512alexandrescu/" var s_server="devnet.developerpipeline.com" var s_channel="http://devnet.developerpipeline.com/cpp/" var s_pageType="/SDMG/Publications/CUJ|/SDMG/Languages/C++" var s_prop1="NO_USER" var s_prop2="" var s_prop3="" var s_prop4="" var s_prop5="" var s_prop6="" var s_prop7="" var s_prop8="" var s_prop9="" var s_prop10="" /* E-commerce Variables */ var s_campaign="" var s_state="" var s_zip="" var s_events="" var s_products="" var s_purchaseID="" var s_eVar1="" var s_eVar2="" var s_eVar3="" var s_eVar4="" var s_eVar5="" var s_account="cmpdevnetdeveloperpipelinecom" /********* INSERT THE DOMAIN AND PATH TO YOUR CODE BELOW ************///--></SCRIPT> <SCRIPT language=JavaScript src="heaplayers-article-cuj_files/s_code_remote.js"></SCRIPT> <!-- End SiteCatalyst code version: G.7. --> <DIV class=border> <TABLE cellSpacing=0 cellPadding=0 width=940 border=0> <TBODY> <TR> <TD vAlign=top align=left><!-- top banner table --> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0> <TBODY> <TR> <TD width=1 bgColor=#ffffff><IMG height=2 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=769 bgColor=#ffffff><IMG height=2 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=769 border=0></TD></TR> <TR> <TD width=1 bgColor=#ffffff><IMG height=94 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD align=middle width=769 bgColor=#ffffff><!-- TOP AD --><!-- AD: 'http://localhost:8085/html.ng/site=sdmg&affiliate=sdmgdeveloperpipeline&pagepos=top&catid=&site_section=9843&articleid=141768&target=cpp&country=&state=' --><!-- Sniffer Code for Flash version=60 --> <SCRIPT language=JavaScript> <!-- var swf_click = "http://as.cmpnet.com/event.ng/Type=click&FlightID=45537&AdID=80364&TargetID=4722&Segments=1411,3108,3448,4875,5817,5871&Targets=2625,2878,4667,4722&Values=34,46,51,63,77,83,90,100,140,203,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/"; var dcswf_click = escape(swf_click); var ShockMode = 0; var plugin = (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) ? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : 0; if (plugin && parseInt(plugin.description.substring(plugin.description.indexOf(".")-1)) >= 6) { ShockMode = 1; } else if (navigator.userAgent && navigator.userAgent.indexOf("MSIE")>=0 && (navigator.userAgent.indexOf("Windows 95")>=0 || navigator.userAgent.indexOf("Windows 98")>=0 || navigator.userAgent.indexOf("Windows NT")>=0)) { document.write('<SCRIPT LANGUAGE=VBScript\> \n'); document.write('on error resume next \n'); document.write('ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.6")))\n'); document.write('<\/SCRIPT\> \n'); } if ( ShockMode ) { document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'); document.write(' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"'); document.write(' ID=flashad WIDTH=728 HEIGHT=90>'); document.write(' <PARAM NAME=movie VALUE="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_728x90c_1209.swf?clickTag='+dcswf_click+'"> '); document.write(' <PARAM NAME=quality VALUE=high> '); document.write(' <PARAM NAME=wmode VALUE=opaque> '); document.write(' <EMBED SRC="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_728x90c_1209.swf?clickTag='+dcswf_click+'" QUALITY=high WMODE=opaque '); document.write(' NAME=flashad swLiveConnect=TRUE WIDTH=728 HEIGHT=90'); document.write(' TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">'); document.write('</EMBED>'); document.write('</OBJECT>'); } else if (!(navigator.appName && navigator.appName.indexOf("Netscape")>=0 && navigator.appVersion.indexOf("2.")>=0)){ document.write('<A HREF="http://as.cmpnet.com/event.ng/Type=click&FlightID=45537&AdID=80364&TargetID=4722&Segments=1411,3108,3448,4875,5817,5871&Targets=2625,2878,4667,4722&Values=34,46,51,63,77,83,90,100,140,203,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target="_top"><IMG SRC="http://i.cmpnet.com/ads/graphics/as5/cc/banner_728x90c.gif" WIDTH=728 HEIGHT=90 BORDER=0></A>'); } //--> </SCRIPT> <NOEMBED><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45537&AdID=80364&TargetID=4722&Segments=1411,3108,3448,4875,5817,5871&Targets=2625,2878,4667,4722&Values=34,46,51,63,77,83,90,100,140,203,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target=_top><IMG height=90 src="heaplayers-article-cuj_files/banner_728x90c.gif" width=728 border=0></A> </NOEMBED><NOSCRIPT><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45537&AdID=80364&TargetID=4722&Segments=1411,3108,3448,4875,5817,5871&Targets=2625,2878,4667,4722&Values=34,46,51,63,77,83,90,100,140,203,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target=_top><IMG height=90 src="heaplayers-article-cuj_files/banner_728x90c.gif" width=728 border=0></A> </NOSCRIPT><IMG height=1 src="" width=1 border=0> </TD> <TR> <TD width=1 bgColor=#ffffff><IMG height=3 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=769 bgColor=#ffffff><IMG height=3 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=769 border=0></TD></TR> <TR> <TD width=770 bgColor=#000066 colSpan=2><IMG height=2 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=770 border=0></TD></TR></TBODY></TABLE><!-- end top banner table --><!-- header table --><MAP id=header name=header><AREA shape=RECT coords=149,22,489,67 href="http://www.developerpipeline.com/"></MAP> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0> <TBODY> <TR height=69> <TD vAlign=top width=68><A href="http://www.cmp.com/"><IMG height=69 hspace=0 src="heaplayers-article-cuj_files/cmp_logo.gif" width=68 border=0></A></TD> <TD vAlign=top><IMG height=69 src="heaplayers-article-cuj_files/top_header.jpg" width=702 useMap=#header border=0></TD></TR></TBODY></TABLE><!-- end header table --><!-- search/utility nav table --> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0> <TBODY> <TR> <TD bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=1 bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=1 bgColor=#ffffff><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=1 bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD></TR> <TR> <TD><SPAN class=side><SPAN class=black12Bold>Developer Network Partners:</SPAN> <IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=10 border=0> <A class=black12Bold href="http://www.cuj.com/">C/C++ Users Journal</A> <IMG height=8 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=10 border=0> <A class=black12Bold href="http://www.ddj.com/">Dr. Dobb's Journal</A> <IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=10 border=0> <A class=black12Bold href="http://www.sdmagazine.com/">Software Development</A> </SPAN></TD> <TD width=1 bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=1 bgColor=#ffffff><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD> <TD width=1 bgColor=#000066><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD><!-- UTILITY NAV --> <TD align=middle><SPAN class=side><A class=black12Bold href="http://www.developerpipeline.com/contact.jhtml">Contact Us</A> <IMG height=8 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=18 border=0> <A class=black12Bold href="http://www.developerpipeline.com/about.jhtml">About Us</A> </SPAN></TD></TR></TBODY></TABLE><!-- end utility nav table --><!-- MAIN NAVIGATION TABS --> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0 table_name="topNavigationTable"> <TBODY> <TR> <TD><A href="http://www.developerpipeline.com/news"><IMG height=29 hspace=0 src="heaplayers-article-cuj_files/nav_news_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/trends"><IMG height=29 hspace=0 src="heaplayers-article-cuj_files/nav_trends_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/howto"><IMG height=29 hspace=0 src="heaplayers-article-cuj_files/nav_howto_dp.gif" border=0></A></TD> <TD><A href="http://productfinder.developerpipeline.com/"><IMG height=29 hspace=0 src="heaplayers-article-cuj_files/nav_productfinder_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/coding"><IMG height=29 alt="Coding & Scripting" hspace=0 src="heaplayers-article-cuj_files/nav_coding_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/design"><IMG height=29 alt="Design & Process" hspace=0 src="heaplayers-article-cuj_files/nav_design_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/tools"><IMG height=29 alt=Tools hspace=0 src="heaplayers-article-cuj_files/nav_tools_dp.gif" border=0></A></TD> <TD><A href="http://www.developerpipeline.com/business"><IMG height=29 alt="Business & Careers" hspace=0 src="heaplayers-article-cuj_files/nav_business_dp.gif" border=0></A></TD></TR></TBODY></TABLE><!-- END MAIN NAVIGATION TABS --><!-- user notification table --><!-- <br> <table border="0" cellpadding="2" cellspacing="1" bgcolor="CC6600"> <tr> <td bgcolor="FFD673">Some content requires registration to the CMP Developer Network. Sign up today!.</td> </tr> </table> --><!-- end user notification table --><!-- MAIN CONTENT TABLE --> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0> <TBODY> <TR> <TD><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=1 border=0></TD></TR> <TR> <TD> <TABLE cellSpacing=0 cellPadding=5 width="100%" border=0> <TBODY> <TR vAlign=top> <TD><A href="http://devnet.developerpipeline.com/">Developer::Pipelines</A> > <A href="http://devnet.developerpipeline.com/cpp/">C++</A><BR><BR></TD> <TD> </TD> <TD align=right><!-- log in --><!-- <a href='https://www.sdmediagroup.com/reg/?site=devnet.developerpipeline.com&content=http://devnet.developerpipeline.com/'><b>LOG IN</b></a> • <a href=/resetpassword.html>Forgot password?</a> • <a href=http://www.sdmediagroup.com/reg/faq.html>Registration FAQ</a> <br> --><!-- end log in --><!-- <a href="javascript:openScript('http://www.sdmediagroup.com/reg/faq.html#compare',650,480)"><img src="/images/new/premium_bullet.gif" hspace="0" vspace="0" border="0"></a> Denotes content for All Access members only --></TD></TR></TBODY></TABLE></TD></TR> <TR> <TD vAlign=top align=left><!-- jumbobox ad --><!-- <table border="0" align="right" cellpadding="5" cellspacing="0"> <tr> <td> <mpdoc:Ad group="sdmg" site="sdmgdeveloperpipeline" pagepos="jumbobox" documentsonly="true" spot="jumbobox"> </td> </tr> </table>--><!-- end jumbobox ad --><!-- IMG height=40 hspace=5 src="java.gif" vspace=5 width=460 --> <H1><FONT color=#5f92c7>Developer::</FONT>C++ Pipeline</H1><!-- -------- BEGIN Nav Anchors --> <P><A class=header href="http://devnet.developerpipeline.com/cpp/index.html#articles">Articles</A> | <A class=header href="http://devnet.developerpipeline.com/cpp/index.html#books">Books</A> | <A class=header href="http://devnet.developerpipeline.com/cpp/index.html#showcase">Products</A> | <A class=header href="http://devnet.developerpipeline.com/cpp/index.html#papers">Whitepapers</A> | <A class=header href="http://devnet.developerpipeline.com/cpp/index.html#events">Training/Conferences</A> | <A class=header href="http://devnet.developerpipeline.com/cpp/index.html#forum">Discussion Forum</A> | <A class=header href="http://syndication.sdmediagroup.com/feeds/public/cmp_devnet_c++.xml">C++ RSS Feed </A></P><!-- -------- END Nav Anchors --><!-- -------- BEGIN Vendor --><!-- AD: 'http://localhost:8085/html.ng/site=sdmg&affiliate=sdmgdeveloperpipeline&pagepos=logo&catid=&site_section=9843&articleid=141768&target=cpp&country=&state=' --><A>This Pipeline Sponsored By: </A><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45541&AdID=75588&TargetID=4729&Segments=1411,3108,3448,4875,5825,5867&Targets=2625,2878,4729&Values=34,46,51,63,77,83,90,100,140,442,618,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/"><IMG src="heaplayers-article-cuj_files/intel_logo2.gif" align=middle border=0></A><IMG height=1 src="" width=1 border=0> <HR align=left noShade SIZE=1> <!-- ---------- End Vendor --><!-- jumbobox ad --> <TABLE cellSpacing=0 cellPadding=5 align=right border=0> <TBODY> <TR> <TD><!-- AD: 'http://localhost:8085/html.ng/site=sdmg&affiliate=sdmgdeveloperpipeline&pagepos=jumbobox&catid=&site_section=9843&articleid=141768&target=cpp&country=&state=' --><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45540&AdID=75586&TargetID=4718&Segments=1411,3108,3448,4569,4875,5819,5866&Targets=2625,2878,3885,4665,4718&Values=34,46,51,63,77,83,90,100,140,290,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=IP,127.0.0.1,&Redirect=http://" target=_parent><IMG height=1 alt="" src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(1).gif" width=1 border=0></A><IMG height=1 src="" width=1 border=0> </TD></TR></TBODY></TABLE><!-- end jumbobox ad --><!--Copyright © C/C++ Users Journal--> <P><I>C/C++ Users Journal</I> December, 2005</P> <H1>Policy-Based Memory Allocation</H1> <H2>Fine-tuning your memory management</H2> <H3>By Andrei Alexandrescu and Emery Berger</H3><I>Andrei Alexandrescu is a graduate student in Computer Science at the University of Washington and author of Modern C++ Design. He can be contacted at andrei@metalanguage.com.</I> <HR> <P>One of the perks of doing hard work for next to no money, an activity also known as being a graduate student, is that you get to rub shoulders with researchers working on interesting problems. I've had the pleasure of meeting in person both Emery Berger and Kathryn McKinley, two of the authors (with Benjamin Zorn) of "Composing High-Performance Memory Allocators" [6], a paper that I found highly interesting for "I can't believe I didn't think of that" reasons. But let's start at the beginning.</P> <P>One chapter of <I>Modern C++ Design</I> [2] is somewhat different than all the others. Actually, very different. While the book is dedicated to creating elegant, flexible, extensible designs, one chapter stands out like a sore thumb by actually describing one fixed, monolithic, rigid, awkward piece of software: Loki's small object allocator. Somehow, I thought that memory management was a low-level operation and, as such, didn't lend itself to the elegant exploits of policy-based design. At the same time, some of the compiler-provided <B>new</B>/<B>delete</B> implementations were pretty bad at dealing with small objects, so I felt there would be a need for something to fill the void. So I sat down and wrote an implementation that has portability as its only merit; other than that, it's not particularly performant, interesting, or original. The main problem with Loki's allocator, however, does not lie in its implementation (which, by the way, has been entirely rewritten by Rich Sposato, to the end of greatly improving its performance), but in its design, which is not configurable nor extensiblejust a few monolithic classes, much like what you'd expect in the bad ol' days.</P> <P>However, at about the same time, Emery Berger and others were experimenting with a mixin-based memory allocator for C++ that is at the same time highly efficient (rivaling the best general-purpose allocators out there), highly customizable (rivaling the best special-purpose allocators, too), and highly portable by virtue of its customizable design! As soon as I became acquainted with that research, I realized what the chapter on memory allocation in <I>Modern C++ Design</I> should have looked like.</P> <P>But before we delve into the fascinating topic of configurable memory allocation, let's tie a few knots with past comments received via e-mail.</P> <H3>Mailcontainer</H3> <P>I wrote the sidebar "Memory: More Than Just Any Resource" in the last Generic<Programming> installment with the serene resignation with which Galileo Galilei must have said his famous "Eppur si muove." "And yet, garbage is collectable," I mumbled into my three-days beard when submitting the article for publication. The expected outcome was that the opponents of garbage collection would exemplarily mortify me via an endless flow of angry e-mails. However, they must've chosen instead to boycott me, because I haven't gotten a single response in protest.</P> <P>Ivan Godard sent me an e-mail on the subject of Observers [3, 4]. That message was so smart, and had me look up words in the dictionary so often, that I've decided to quote it almost in entirety, at the risk of blowing up the size of this article:</P> <BLOCKQUOTE>Your difficulties with <B>attach</B> and <B>detach</B> while in the middle of notification are canonical concurrency problems, and can be dealt with in the usual way. The (only reasonable?) semantics for Observer is to see <B>subject</B>, <B>observer</B>, and <B>event</B> as three independent and asynchronous processes, with a time stream localized at <B>subject</B>. That is, an <B>observer</B> cannot directly determine the time relation between its attempt to attach and the occurrence of a particular event because the event is not within the observer's horizon. Only the <B>subject</B>, which receives both events and requests to <B>attach</B>, can time-order these.<BR><BR>Consequently a putative observer will see some sequence of events that (in the subject's time frame) begins some time after the attempt to attach and ends some time after the attempt to detach. The sequence is guaranteed to be ordered (in subject time) and dense, but where it starts and where it ends is not known. Of course, if the observer is itself a source of events and the channel between observer and subject is order-preserving, then the observer can enforce somewhat more stringent bounds on how far the observed sequence extends into the subject's past or subject's future by injecting an event just before the attach or just after the detach.<BR><BR>So much for relativity theory. In practice, this implements naturally by considering the attempt to attach and the attempt to detach as being themselves events. The subject enqueues an event (including an <B>attach</B>/ <B>detach</B>) on an action list, and walks the list of observers applying each event in turn to each observer. Both observers and events are timestamped; a simple counter will do. Events are discarded when there are no observers with lesser stamps. The observer list is preceded by an observer (the subject itself) that is watching for attach events and that adds the observer to the observer list. All observers are watching for their own detach events and remove themselves when the subject applies the corresponding detach event. [...]<BR><BR>Most of the difficulties you encountered appear to be a consequence of the assumption that attach and detach were somehow global and absolute, rather than just another event in the sequence of events encountered by the subject. Remove that mistaken idea and your invalidated-iterators problems disappear.<BR></BLOCKQUOTE> <P>This view of attachment and detachment as simple events is very interesting. This generalization would, however, make it harder to define policies that lead to the simple implementations in the article. Let's admit, such simple solutions are widely used and have their place in spite of their risks and limitations. If anyone would like to embark on defining a policy-based design for such a "relativistic" Observer, and if the design does allow efficient simple implementations as well, I'd be highly interested. Contact Ivan at igodard@pacbell.net with questions.</P> <P>Brian Wood comments on the "Walking Down Memory Lane" article:</P> <BLOCKQUOTE>While you introduce <B>auto_vector</B>, you didn't mention either of the <B>ptr_vector</B> implementations. Thorsten Ottosen has written an interesting article about <B>ptr_vector</B> in the October 2005 issue of <I>Dr. Dobb's Journal</I>. <B>auto_vector</B> and the <B>ptr_vector</B> by Ottosen are obviously closely related, but also have differences. Some mention to <B>ptr_vector</B> and the differences would have been helpful, I think.<BR><BR>Anyway, from my own experience, I agree with you that things like <B>auto_vector</B> and <B>ptr_vector</B> are often preferable to <B>vector<shared_ptr<T> ></B>.<BR></BLOCKQUOTE> <P>Great, thanks Brianand readership, consider yourself tipped on where to look for more material related to scoped memory management.</P> <H3>Memory Allocation: One Size Doesn't Fit ll</H3> <P>Today's general-purpose memory allocators have reached reasonable speed and low fragmentation for a large category of programs. However, in the memory-allocation realm, a little information can go a long way. Application-specific information about allocation patterns helps to implement specialized memory allocators that heavily improve the bottom line of many high-performance applications. Sometimes, as little intel as "Blocks of size 80 are allocated more often than blocks of all other sizes," when properly used (as we'll discuss soon), can incredibly improve the bottom-line runtime of a program. (Caveat: Sometimes customized allocators are no better, and can be worse, than general-purpose allocatorssee the paper "Reconsidering Custom Memory Allocation" [7] for more details.) While general-purpose allocators have average overheads in the hundreds of cycles, a good customized memory allocator can require as few as half a dozen cycles.</P> <P>That's why many high-profile, high-performance applications (GCC, Apache, and Microsoft's SQL Server to name just a few) implement their own memory allocator. A good idea, then, is to generalize such good specialized allocators and put them in a library. But "generalization" and "specialization" are in tension: Your application might have different allocation patterns that would require yet another behavior from your allocator. What to do?</P> <P>But wait, there's more. If we do devise a method to easily create special-purpose memory allocators, we can go full-circle and define a general-purpose allocator as a combination of wisely chosen special-purpose allocators. If the resulting general-purpose allocator compares favorably with the existing monolithic general-purpose allocators, then the design is valid and useful.</P> <P>Emery's team worked towards that idea, leading to their library HeapLayers (http://heaplayers.org/). To define configurable allocators, they used mixins (also known as Coplien's curiously recurring pattern in the C++ community): defining classes with a parameterized base. Each layer defines only two member functions, <B>malloc</B> and <B>free</B>:</P><PRE>template <class T> struct Allocator : public T { void * malloc(size_t sz); void free(void* p); // system-dependent value enum { Alignment = sizeof(double) }; // optional interface size_t getSize(const void* p); }; </PRE> <P>Each layer implementation would get a crack on allocation and deallocation, possibly (and likely) requesting memory from its base class. A self-contained allocator sits at the very top of the hierarchyone that forwards requests straight to the system's <B>new</B> and <B>delete</B> operators, <B>malloc</B> and <B>free</B> functions, and the such. In HeapLayers terminology, these are the top heaps. To exemplify (careful with the qualifications so we don't enter infinite recursion):</P><PRE>struct MallocHeap { void * malloc(size_t sz) { return std::malloc(sz); } void free(void* p) { return std::free(p); } }; </PRE> <P>Top heaps can also be implemented around system calls for getting memory, such as UNIX's <B>sbrk</B> or <B>mmap</B>. This is necessary when you're completely replacing <B>malloc</B> and friends.</P> <P>The <B>getSize</B> function has a special status. Not everybody is going to need it, so defining it is optional (if you combine the wrong layers, the compiler will tell you). If it does, all you have to do is insert a layer that stores the block size and offers the <B>getSize</B> primitive; see <A href="http://devnet.developerpipeline.com/documents/s=9843/q=1/cuj0512alexandrescu/0512alexandrescul1.html" target=_BLANK>Listing 1</A>.</P> <P><B>SizeHeap</B> is the perfect illustration of how to implement a useful layer that hooks into its base's <B>malloc</B> and <B>free</B> functions, does something extra, and returns "doctored" results to the client. <B>SizeHeap</B> does its work by allocating extra memory to store the block size, with the appropriate cautions (the union) to stay as immune as possible to the alignment issue. The client gets access to the memory right next to that extra data. It's not hard to imagine building a debug heap that pads the memory block before and after with some bytes filled with a particular pattern, and then verify for overruns by checking whether the pattern has been preserved. In fact, that's exactly what HeapLayers' <B>DebugHeap</B> layer does. Pretty neat.</P> <P>But wait, something's suboptimal here. Some systems already offer a primitive to compute the size of a <B>malloc</B>ated block. On those systems, <B>SizeHeap</B> would actually waste space. In that case (for example, on Microsoft Visual C++), you wouldn't need <B>SizeHeap</B> in conjunction with <B>MallocHeap</B>, because <B>MallocHeap</B> would implement <B>getSize</B> out of the box:</P><PRE>struct MallocHeap { ... as above ... size_t getSize(void* p) { return _msize(p); } }; </PRE> <P>But wait, something's still suboptimal here. Remember, we're counting cycles. What if a system's <B>malloc</B> documentation states that the block size is stored in a word prior to the actual block? In that case, <B>SizeHeap</B> would still waste memory by storing yet another word next to the one already planted by the system. What's needed is a layer that implements <B>getSize</B> just the way <B>SizeHeap</B> does, but doesn't hook <B>malloc</B> and <B>free</B>. That's why <B>HeapLayers</B> segregates the previously shown <B>SizeHeap</B> in two; see <A href="http://devnet.developerpipeline.com/documents/s=9843/q=1/cuj0512alexandrescu/0512alexandrescul2.html" target=_BLANK>Listing 2</A>.</P> <P>Now <B>SizeHeap</B> always (correctly) adds the <B>UseSizeHeap</B> layer and exploits its <B>getSize</B> implementation, while <B>UseSizeHeap</B> can also be used in other configurationsa very elegant design.</P> <H3>A Useful Example: FreelistHeap</H3> <P>Let's face it, so far we have kind of set up the stage. We do have an architecture, but no clue on how to write an efficient specialized allocator using layers. A popular and "most bang for the buck" strategy is the following:</P> <OL> <LI>Collect stats about your application's allocation counts for each size. <LI>For the most often asked size (call it <B>S</B>), maintain a private, singly linked list. <LI>Memory allocations for <B>S</B> return memory from that list if possible, or else from the default allocator (in a layered architecture, from the superior layer). <LI>Memory deallocations for blocks of size <B>S</B> push the block into the list. </LI></OL> <P>A refinement of the strategy would be to use the same free list for a range of sizes <B>S1</B> to <B>S2</B>, at the cost of some slack memory. The needed singly linked list operations are <B>O(1)</B> and actually only a few instructions. In addition, the pointer to the next item can be stored in the actual block (the block stores no useful datait's always a freed block!) so there's no extra memory required per block. Given that most applications' allocation size distribution is highly skewed, free lists are any allocator implementer's indispensable utensil.</P> <P>Let's implement a layer that implements a free list for a range of statically known sizes <B>S1</B> to <B>S2</B>; see <A href="http://devnet.developerpipeline.com/documents/s=9843/q=1/cuj0512alexandrescu/0512alexandrescul3.html" target=_BLANK>Listing 3</A>.</P> <P>Now you can define a custom heap like this:</P><PRE>typedef FLHeap< SizeHeap<MallocHeap>, 24, 32> SmartoHeapo; </PRE> <P><B>SmartoHeapo</B> will be superfast for allocation sizes between 24 and 32, and pretty much the same for all other sizes.</P> <H3>In-Place Resizing</H3> <P>Many a C++ programmer has been dreaming for a standard primitive to reallocate memory in place. You see, C has <B>realloc</B>, which can do in-place reallocation if possible, or use <B>memcpy</B> when it comes about copying data around. But <B>memcpy</B> doesn't work for C++ objects, so <B>realloc</B> doesn't work for C++ objects,; therefore, any sort of renew primitive can't be implemented using the Standard C allocator. So C++ doesn't have renew [1].</P> <P>To give you an idea of the improvements that in-place reallocation can bring to C++ code, consider:</P><PRE>const int n = 10000; Vec v; for (int i = 0; i < n; ++i) v.push_back(0); </PRE> <P>Howard Hinnant of Metrowerks has been working on implementing in-place expansion for CodeWarrior's Standard Library implementation. In Howard's own words:</P> <BLOCKQUOTE>I currently have a <B>vector<T, malloc_allocator<T> ></B> that does [...] expand-in-place based on N1085 [8]. It blows the doors off a built-in C-like array! :-) When <B>Vec</B> is a <B>vector<int></B> without expand-in-place: <PRE>0.00095674 seconds</PRE>When <B>Vec</B> is a <B>vector<int></B> with expand-in-place: <PRE>0.000416943 seconds</PRE>The timings should only be trusted to two significant digits. But rest assured, I've done the work to secure those two digits. We are not looking at an anomaly here. </BLOCKQUOTE><PRE></PRE> <P>Given the benefits of in-place resizing and that each heap layer has control over its own allocation algorithms and data structures, let's augment the heap-layer interface:</P><PRE>template <class T> struct Allocator : public T { void * malloc(size_t sz); void free(void* p); size_t expand(void* p, size_t min, size_t max); }; </PRE> <P>The semantics of expand is, try to expand the block pointed to by <B>p</B> to the largest size possible between <B>min</B> and <B>max</B>. Then return whatever size you could expand the memory to, or zero if no expansion was possible. Fortunately, things can be arranged such that a layer doesn't have to fuss about the expand routine unless it wants to. That works if all top allocators inherit the following little class:</P><PRE>struct TopHeap { size_t expand(void*, size_t, size_t) { return 0; } // not intended for standalone usage protected: ~TopHeap() {} }; </PRE> <H3>Conclusion</H3> <P>Configurable memory allocation is, as Emery's research has shown, a practical, all-in-one alternative to both specialized and general-purpose allocators. Emery's numbers (refer to the paper [6] for details) consistently show that allocators created with HeapLayers perform just as well as, or better than, monolithic allocators, be they general-purpose or specialized. Moreover, HeapLayers' layered architecture encourages easier experimentation, simpler debugging, and unparalleled extensibility. Instead of being an oddball chapter of <I>Modern C++ Design</I>, memory allocation should have been one of the best success stories of policy-based design.</P> <P><A href="http://devnet.developerpipeline.com/documents/s=9843/q=1/cuj0512alexandrescu/0512alexandrescut1.html" target=_BLANK>Table 1</A> shows a relevant subset of the layers implemented in HeapLayers. There would be a lot of goodies to discuss, such as the locked heaps for multithreaded operations, the STL adapter, the various utility heaps, or how the layers can be combined to create a general-purpose allocator. But conventional wisdom warns us that "The mind can only enjoy what the butt can endure," so it's about time to shut downwithout forgetting to release the memory in destructors. Happy coding.</P> <H3>References</H3> <OL> <LI>Alexandrescu, Andrei. "Generic<Programming>: Typed Buffers (III)," <I>C++ Experts Online</I>, December 2001. Available at http://erdani.org/ publications/cuj-12-2001.html. <LI>Alexandrescu, Andrei. <I>Modern C++ Design</I>, Addison-Wesley Longman, 2001. <LI>Alexandrescu, Andrei. "Generic<Programming>: Prying Eyes: A Policy-Based Observer (I)," <I>C++ Users Journal</I>, April 2005. <LI>Alexandrescu, Andrei. "Generic<Programming>: Prying Eyes: A Policy-Based Observer (II)," <I>C++ Users Journal</I>, June 2005. <LI>Berger, Emery D., Kathryn S. McKinley, Robert D. Blumofe, and Paul R. Wilson. "Hoard: A scalable memory allocator for multithreaded applications. In International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS-IX), pp. 117-128. Cambridge, MA, November 2000; http://citeseer.ist.psu.edu/berger00hoard.html. <LI>Berger, Emery D., Benjamin G. Zorn, and Kathryn S. McKinley. "Composing High-Performance Memory Allocators," in SIGPLAN Conference on Programming Language Design and Implementation, pp. 114-124, 2001; http://citeseer.ist.psu.edu/berger01composing.html. <LI>Berger, Emery D., Benjamin G. Zorn, and Kathryn S. McKinley. "Reconsidering custom memory allocation," in Proceedings of the Conference on Object-Oriented Programming Systems, Languages, and Applications (OOPSLA) 2002. Seattle, Washington, November 2002; http://citeseer.ist.psu.edu/berger02reconsidering.html. <LI>Hinnant, Howard. Proposal to augment the interface of malloc/free/realloc/calloc. See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1085.htm.</LI></OL> <H5>CUJ</H5> <P> </P> <TABLE cellSpacing=1 cellPadding=5 width="100%" bgColor=#000000 border=0> <TBODY> <TR vAlign=top bgColor=#ffffff> <TD width="50%"><!-- -------------------- BEGIN Forum --><A class=header name=forum>From our C Discussion Forum</A><BR><A href="http://devnet.developerpipeline.com/forums/thread.html?forumid=64&threadid=23245">Serial USB support and code</A><BR><!MESSAGE!><BR><A href="http://devnet.developerpipeline.com/forums/thread.html?forumid=64&threadid=23242">ATA PC Card Identify Drive</A><BR><!MESSAGE!><BR><A href="http://devnet.developerpipeline.com/forums/thread.html?forumid=64&threadid=23239">need Mathematic lib source code </A><BR><!MESSAGE!><BR><A href="http://devnet.developerpipeline.com/forums/forum.html?forumid=64">Visit the C Forum</A> <!-- -------------------- END Forum --></TD> <TD width="50%"><A class=header>C++ related Articles</A> <BR><B><A href="http://devnet.developerpipeline.com/documents/s=9843/q=1/ddj050820pc/ddj050820pc.mp3">Eclipse CDT 3.0 Released</A></B><BR><BR></TD></TR></TBODY></TABLE></TD><!-- divider columns --></TR> <TR> <TD vAlign=top align=left height=10><IMG height=10 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=770 border=0></TD></TR></TBODY></TABLE><!-- END MAIN CONTENT TABLE --><!-- BOTTOM NAVIGATION --> <TABLE cellSpacing=0 cellPadding=0 width=770 bgColor=#ffffff border=0 table_name="footerTable"> <TBODY> <TR> <TD align=middle bgColor=#999999><IMG height=2 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=770 border=0></TD></TR> <TR> <TD> <DIV class=BOTnav><A class=blacknavigation href="http://www.developerpipeline.comnews/">News</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/trends">Trends</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://productfinder.developerpipeline.com/">Product Finder</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/howto">How-To</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/coding">Coding & Scripting</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/design">Design & Process</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/tools">Tools</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/business">Business & Careers</A> <BR><A class=blacknavigation href="http://www.developerpipeline.com/newsletter.jhtml">Free Newsletters</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/glossary.jhtml">Developer Glossary</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/contact.jhtml">Contact Us</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.developerpipeline.com/about.jhtml">About Us</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.cmp.com/delivery/privacy.html">Privacy</A> <IMG height=11 hspace=5 src="heaplayers-article-cuj_files/orangeline.gif" width=2 border=0 valign="absbottom"> <A class=blacknavigation href="http://www.cmp.com/delivery/privacy.html#california">Your California Privacy Rights</A> </DIV></TD></TR> <TR> <TD align=middle bgColor=#999999><IMG height=1 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=770 border=0></TD></TR> <TR> <TD><!-- indusrty brains table --> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD vAlign=center align=middle><BR><BR><!-- indusrty brains --><SPAN id=nointelliTXT> <TABLE cellSpacing=2 cellPadding=0 width="90%" bgColor=#223378 border=0> <TBODY> <TR> <TD> <TABLE class=txtBlk_small cellSpacing=0 cellPadding=5 width="100%" bgColor=#efefef border=0> <TBODY> <TR> <TD> <DIV align=center><SPAN class=txtBlk_small><B>MarketPlace</B></SPAN></DIV><BR> <DIV align=center><A href="http://www.industrybrains.com/cmpsd">Wanna see your ad here?</A></DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></SPAN><!-- end IB --></TD></TR></TBODY></TABLE><BR><!-- end indusrty brains table--> <DIV class=BOTnav><A class=orange11 href="http://www.internetweek.com/"></A>Developer Network Websites: <A class=orange11 href="http://www.byte.com/" target=_blank>BYTE.com</A>, <A class=orange11 href="http://www.cuj.com/" target=_blank>C/C++ Users Journal</A>, <A class=orange11 href="http://developerpipeline.com/" target=_blank>Developer Pipeline</A>, <A class=orange11 href="http://www.ddj.com/" target=_blank>Dr. Dobb's Journal</A>, <A class=orange11 href="http://www.dotnetjunkies.com/" target=_blank>DotNetJunkies</A>, <A class=orange11 href="http://msdn.microsoft.com/msdnmag/" target=_blank>MSDN Magazine</A>, <A class=orange11 href="http://www.samag.com/" target=_blank>Sys Admin</A>, <A class=orange11 href="http://www.sdexpo.com/" target=_blank>SD Expo</A>, <A class=orange11 href="http://www.sdmagazine.com/" target=_blank>Software Development Magazine</A>, <A class=orange11 href="http://www.sqljunkies.com/" target=_blank>SqlJunkies</A>, <A class=orange11 href="http://www.unixreview.com/" target=_blank>Unixreview</A>, <A class=orange11 href="http://www.windevnet.com/" target=_blank>Windows Developer Network</A>, <A class=orange11 href="http://www.newarchitectmag.com/" target=_blank>New Architect</A> </DIV></TD></TR> <TR> <TD align=middle bgColor=#cccccc> <DIV class=BOTnavgrey><SPAN class=grey9><A class=grey9 href="http://www.cmp.com/delivery/copyright.html">Copyright</A> © 2005<A class=grey9 href="http://www.cmp.com/">CMP Media LLC.</A> | DEVELOPER PIPELINE All rights reserved. <A class=grey9 href="http://www.cmp.com/delivery/privacy.html">Privacy Policy</A> | <A href="http://www.cmp.com/delivery/privacy.html#california">Your California Privacy Rights</A> | <A class=grey9 href="http://www.cmp.com/delivery/terms.html">Terms of Service</A> </SPAN></DIV></TD></TR> <TR> <TD align=middle bgColor=#e7e7e7><IMG height=2 hspace=0 src="heaplayers-article-cuj_files/blank.gif" width=770 border=0></TD></TR></TBODY></TABLE><!-- END BOTTOM NAVIGATION --><!-- bottom ad --> <DIV align=center><BR><BR><!-- AD: 'http://localhost:8085/html.ng/site=sdmg&affiliate=sdmgdeveloperpipeline&pagepos=bottom&catid=&site_section=9843&articleid=141768&target=cpp&country=&state=' --><!-- Sniffer Code for Flash version=60 --> <SCRIPT language=JavaScript> <!-- var swf_click = "http://as.cmpnet.com/event.ng/Type=click&FlightID=45538&AdID=80366&TargetID=4721&Segments=1411,3108,3448,4875,5818,5864&Targets=2625,2878,4666,4721&Values=34,46,51,63,77,83,90,100,140,204,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/"; var dcswf_click = escape(swf_click); var ShockMode = 0; var plugin = (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) ? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : 0; if (plugin && parseInt(plugin.description.substring(plugin.description.indexOf(".")-1)) >= 6) { ShockMode = 1; } else if (navigator.userAgent && navigator.userAgent.indexOf("MSIE")>=0 && (navigator.userAgent.indexOf("Windows 95")>=0 || navigator.userAgent.indexOf("Windows 98")>=0 || navigator.userAgent.indexOf("Windows NT")>=0)) { document.write('<SCRIPT LANGUAGE=VBScript\> \n'); document.write('on error resume next \n'); document.write('ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.6")))\n'); document.write('<\/SCRIPT\> \n'); } if ( ShockMode ) { document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'); document.write(' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"'); document.write(' ID=flashad WIDTH=728 HEIGHT=90>'); document.write(' <PARAM NAME=movie VALUE="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_728x90c_1209.swf?clickTag='+dcswf_click+'"> '); document.write(' <PARAM NAME=quality VALUE=high> '); document.write(' <PARAM NAME=wmode VALUE=opaque> '); document.write(' <EMBED SRC="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_728x90c_1209.swf?clickTag='+dcswf_click+'" QUALITY=high WMODE=opaque '); document.write(' NAME=flashad swLiveConnect=TRUE WIDTH=728 HEIGHT=90'); document.write(' TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">'); document.write('</EMBED>'); document.write('</OBJECT>'); } else if (!(navigator.appName && navigator.appName.indexOf("Netscape")>=0 && navigator.appVersion.indexOf("2.")>=0)){ document.write('<A HREF="http://as.cmpnet.com/event.ng/Type=click&FlightID=45538&AdID=80366&TargetID=4721&Segments=1411,3108,3448,4875,5818,5864&Targets=2625,2878,4666,4721&Values=34,46,51,63,77,83,90,100,140,204,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target="_top"><IMG SRC="http://i.cmpnet.com/ads/graphics/as5/cc/banner_728x90c.gif" WIDTH=728 HEIGHT=90 BORDER=0></A>'); } //--> </SCRIPT> <NOEMBED><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45538&AdID=80366&TargetID=4721&Segments=1411,3108,3448,4875,5818,5864&Targets=2625,2878,4666,4721&Values=34,46,51,63,77,83,90,100,140,204,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target=_top><IMG height=90 src="heaplayers-article-cuj_files/banner_728x90c.gif" width=728 border=0></A> </NOEMBED><NOSCRIPT><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45538&AdID=80366&TargetID=4721&Segments=1411,3108,3448,4875,5818,5864&Targets=2625,2878,4666,4721&Values=34,46,51,63,77,83,90,100,140,204,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/" target=_top><IMG height=90 src="heaplayers-article-cuj_files/banner_728x90c.gif" width=728 border=0></A> </NOSCRIPT><IMG height=1 src="" width=1 border=0> </DIV><!-- end bottom ad --><BR><FONT size=-1>web2 </FONT></TD> <TD vAlign=top align=right width=170><!-- right column --> <TABLE cellSpacing=0 cellPadding=0 width=160 border=0> <TBODY> <TR> <TD><!-- streaming media --> <DIV style="MARGIN-TOP: 170px"> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD bgColor=#cc6600> <TABLE cellSpacing=0 cellPadding=3 width="100%" border=0> <TBODY> <TR> <TD><FONT color=#ffffff><STRONG>DevNet Podcasts</STRONG></FONT> </TD></TR></TBODY></TABLE></TD></TR> <TR> <TD bgColor=#ffd673 height=2></TD></TR></TBODY></TABLE> <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0> <TBODY> <TR> <TD width=1 bgColor=#999999><IMG height=1 hspace=0 src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(2).gif" width=1 border=0></TD> <TD bgColor=#ffffff> <TABLE cellSpacing=0 cellPadding=5 width="100%" border=0> <TBODY> <TR> <TD> <P><STRONG>Introducing Dobbscast Audio Blogs</STRONG></P> <P align=left><A href="http://syndication.sdmediagroup.com/feeds/public/cmp_podcast_ddj.xml">Get the Dobbscast feed<BR><IMG alt="" src="heaplayers-article-cuj_files/rss_podcast.gif" border=0></A></P></TD></TR></TBODY></TABLE></TD> <TD width=1 bgColor=#999999><IMG height=1 hspace=0 src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(2).gif" width=1 border=0></TD></TR> <TR> <TD bgColor=#999999><IMG height=1 hspace=0 src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(2).gif" width=1 border=0></TD> <TD bgColor=#999999><IMG height=1 hspace=0 src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(2).gif" width=1 border=0></TD> <TD bgColor=#999999><IMG height=1 hspace=0 src="C:\home\emery\projects\heaplayers\doc\heaplayers-article-cuj_files\blank(2).gif" width=1 border=0></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></DIV><!-- end streaming media --><!-- skyscraper ad --><BR> <DIV align=center><!-- AD: 'http://localhost:8085/html.ng/site=sdmg&affiliate=sdmgdeveloperpipeline&pagepos=sky&catid=&site_section=9843&articleid=141768&target=cpp&country=&state=' --><!-- Sniffer Code for Flash version=60 --> <SCRIPT language=JavaScript> <!-- var swf_click = "http://as.cmpnet.com/event.ng/Type=click&FlightID=45539&AdID=80365&TargetID=4720&Segments=1411,3108,3219,3448,4875,5820,5869&Targets=2625,2781,2878,4664,4720&Values=34,46,51,63,77,83,90,100,140,206,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/products/"; var dcswf_click = escape(swf_click); var ShockMode = 0; var plugin = (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) ? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : 0; if (plugin && parseInt(plugin.description.substring(plugin.description.indexOf(".")-1)) >= 6) { ShockMode = 1; } else if (navigator.userAgent && navigator.userAgent.indexOf("MSIE")>=0 && (navigator.userAgent.indexOf("Windows 95")>=0 || navigator.userAgent.indexOf("Windows 98")>=0 || navigator.userAgent.indexOf("Windows NT")>=0)) { document.write('<SCRIPT LANGUAGE=VBScript\> \n'); document.write('on error resume next \n'); document.write('ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.6")))\n'); document.write('<\/SCRIPT\> \n'); } if ( ShockMode ) { document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'); document.write(' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"'); document.write(' ID=flashad WIDTH=125 HEIGHT=600>'); document.write(' <PARAM NAME=movie VALUE="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_125x600a_1209.swf?clickTag='+dcswf_click+'"> '); document.write(' <PARAM NAME=quality VALUE=high> '); document.write(' <PARAM NAME=wmode VALUE=opaque> '); document.write(' <EMBED SRC="http://i.cmpnet.com/ads/graphics/as5/cc/flash/banner_125x600a_1209.swf?clickTag='+dcswf_click+'" QUALITY=high WMODE=opaque '); document.write(' NAME=flashad swLiveConnect=TRUE WIDTH=125 HEIGHT=600'); document.write(' TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">'); document.write('</EMBED>'); document.write('</OBJECT>'); } else if (!(navigator.appName && navigator.appName.indexOf("Netscape")>=0 && navigator.appVersion.indexOf("2.")>=0)){ document.write('<A HREF="http://as.cmpnet.com/event.ng/Type=click&FlightID=45539&AdID=80365&TargetID=4720&Segments=1411,3108,3219,3448,4875,5820,5869&Targets=2625,2781,2878,4664,4720&Values=34,46,51,63,77,83,90,100,140,206,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/products/" target="_top"><IMG SRC="http://i.cmpnet.com/ads/graphics/as5/cc/banner_125x600a.gif" WIDTH=125 HEIGHT=600 BORDER=0></A>'); } //--> </SCRIPT> <NOEMBED><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45539&AdID=80365&TargetID=4720&Segments=1411,3108,3219,3448,4875,5820,5869&Targets=2625,2781,2878,4664,4720&Values=34,46,51,63,77,83,90,100,140,206,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/products/" target=_top><IMG height=600 src="heaplayers-article-cuj_files/banner_125x600a.gif" width=125 border=0></A> </NOEMBED><NOSCRIPT><A href="http://as.cmpnet.com/event.ng/Type=click&FlightID=45539&AdID=80365&TargetID=4720&Segments=1411,3108,3219,3448,4875,5820,5869&Targets=2625,2781,2878,4664,4720&Values=34,46,51,63,77,83,90,100,140,206,442,645,646,657,944,945,1184,1311,1405,1412,1426,1716,1736,1767,1785,1935,1936,1944,1970,2310,2327,2352,2759,2767,2862,2878,2942,3067,3080&RawValues=&Redirect=http://www.intel.com/software/products/" target=_top><IMG height=600 src="heaplayers-article-cuj_files/banner_125x600a.gif" width=125 border=0></A> </NOSCRIPT><IMG height=1 src="" width=1 border=0> </DIV><!-- end skyscraper --></TD></TR></TBODY></TABLE><!-- end right column --></TD></TR></TBODY></TABLE></DIV></BODY></HTML>