<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5280200963174451807</id><updated>2012-01-04T17:18:45.256Z</updated><category term='windows'/><category term='design'/><category term='unicode'/><category term='iphone'/><category term='snippet'/><category term='configury'/><category term='c++'/><category term='geeky'/><category term='patterns'/><category term='rant'/><title type='text'>Whitebait, Kleftiko, Ekmek Special</title><subtitle type='html'>Not in fact any relation to the famous large Greek meal of the same name.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4648628565652330379</id><published>2012-01-04T17:17:00.000Z</published><updated>2012-01-04T17:18:45.264Z</updated><title type='text'>Giving An FTDI Serial Port A Persistent Device Node</title><content type='html'>&lt;p&gt;There are plenty of perfectly good reasons why one might have
several &lt;a href=http://www.ladyada.net/make/boarduino/use.html&gt;&lt;sc&gt;FTDI&lt;/sc&gt;
USB-to-serial adaptors&lt;/a&gt; attached to the same PC at the same
time. Anyone who does, though, will notice that they&amp;rsquo;re a royal pain,
because every time you unplug and replug one, it gets a
&lt;i&gt;different&lt;/i&gt; &lt;tt&gt;/dev/ttyUSB&lt;/tt&gt;&lt;i&gt;n&lt;/i&gt; device node.
&lt;/p&gt;

&lt;p&gt;Fortunately, there&amp;rsquo;s a way to use udev to set up unchanging aliases
for those ever-changing device nodes. This is done by setting up a
udev rule for each &lt;sc&gt;FTDI&lt;/sc&gt; adaptor that you care about, that picks it out
by serial number and gives it a custom symlink.
&lt;/p&gt;

&lt;p&gt;Some of the details are &lt;a
href="http://wiki.debian.org/udev"&gt;here&lt;/a&gt;, but just to sew it all
together, here&amp;rsquo;s what you need to do.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;First attach your &lt;sc&gt;FTDI&lt;/sc&gt; adaptor,
making sure all others are unplugged.&lt;/p&gt;

&lt;li&gt;&lt;tt&gt;ls /dev/ttyUSB*&lt;/tt&gt;&lt;br&gt;&amp;mdash; only one should be listed.

&lt;li&gt;&lt;tt&gt;udevadm info --name=/dev/ttyUSB0 --attribute-walk&lt;/tt&gt;
&lt;br&gt;&amp;mdash; (using the ttyUSB number listed in the previous step) should dump a huge list of attributes

&lt;li&gt;&lt;tt&gt;udevadm info --name=/dev/ttyUSB0 --attribute-walk | grep serial&lt;/tt&gt;
&lt;br&gt;&amp;mdash; will list only a few lines, such as the following &amp;mdash;

&lt;blockquote&gt;&lt;tt&gt;    SUBSYSTEMS=="usb-serial"&lt;br&gt;
    ATTRS{serial}=="XR00U1BU"&lt;br&gt;
    ATTRS{serial}=="000000000000"&lt;br&gt;
    ATTRS{serial}=="0000:00:1d.7"&lt;/tt&gt;&lt;/blockquote&gt;

&lt;li&gt;The first &lt;sc&gt;ATTRS&lt;/sc&gt; line is the one we&amp;rsquo;re interested
in. That&amp;rsquo;s the USB serial number of the &lt;sc&gt;FTDI&lt;/sc&gt; adaptor. (The
subsequent lines are the USB serial number of an intermediate hub, and
the PCI address of the USB controller.)

&lt;li&gt;Now you need to go and find the udev rules directory: in a
standard udev install, that&amp;rsquo;s &lt;tt&gt;/etc/udev/rules.d&lt;/tt&gt;. In that
directory, make a file called &lt;tt&gt;10-local.rules&lt;/tt&gt; (you&amp;rsquo;ll need to
be root), and add a line like the following (and it must be all on one
line; this blog might show it split) &amp;mdash;&lt;br&gt;

&lt;blockquote&gt;&lt;tt&gt;KERNEL=="ttyUSB?", ATTRS{serial}=="XR00U1BU", SYMLINK+="ftdiDUINO", MODE="0666"&lt;/tt&gt;&lt;/blockquote&gt;

&lt;li&gt;Obviously the &lt;sc&gt;ATTRS&lt;/sc&gt; clause must match the one your
adaptor listed above. The &lt;sc&gt;SYMLINK&lt;/sc&gt; clause can be anything
(that doesn&amp;rsquo;t clash with any other device), so name it after the thing
it&amp;rsquo;s plugged into at the other end.

&lt;li&gt;Unplug and replug your &lt;sc&gt;FTDI&lt;/sc&gt; adaptor. Whatever ttyUSB number it gets, the symlink &lt;tt&gt;/dev/ftdiDUINO&lt;/tt&gt; will be pointing to it.

&lt;li&gt;Oh yes, that udev rule also makes the device node world-writable. So you won&amp;rsquo;t need to be root to issue
&lt;blockquote&gt;&lt;tt&gt;miniterm.py /dev/ftdiDUINO 115200&lt;/tt&gt;&lt;/blockquote&gt;

&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4648628565652330379?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4648628565652330379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2012/01/giving-ftdi-serial-port-persistent.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4648628565652330379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4648628565652330379'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2012/01/giving-ftdi-serial-port-persistent.html' title='Giving An FTDI Serial Port A Persistent Device Node'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-5412515248403922029</id><published>2011-04-09T22:54:00.002+01:00</published><updated>2011-04-16T17:41:21.269+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>The Failure Mode Of Agile Development</title><content type='html'>&lt;p&gt;Here&amp;rsquo;s the &amp;ldquo;traditional&amp;rdquo; waterfall model of
software development:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
+------------+------------+------------+
| Design     | Implement  | Test       |
+------------+------------+------------+
^ Start                                ^ Deadline
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;And here&amp;rsquo;s its almost inevitable failure mode: design takes
too long, or implementation takes too long, but the deadline
doesn&amp;rsquo;t move, so test is cut short and the product ships full of
bugs:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------+.....+
| Design        | Implement     | Test |
+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------+.....+
^ Start                                ^ Deadline
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Software development organisations have been wearily familiar with
this outcome, whether in their own code or other people&amp;rsquo;s, since
at least &lt;a
href="http://www.amazon.co.uk/Mythical-Month-Essays-Software-Engineering/dp/0201835959"&gt;Brooks
(1975)&lt;/a&gt;. Both the cause and the effect of schedule crunch are
widely-known and well-understood: often the effect is &lt;em&gt;so&lt;/em&gt;
well-known that it can be specifically detected by reviewers and
end-users.&lt;/p&gt;

&lt;p&gt;Here, by contrast, is the fashionable new agile model:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
+------------+------------+------------+
| Red        | Green      | Refactor   |
+------------+------------+------------+
^ Start                                ^ Deadline
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;In this case, &amp;ldquo;red&amp;rdquo; means you write the unit-tests
first, but of course they fail (red light), because you haven&amp;rsquo;t
written the code yet. Then you write the code, so they pass
(&amp;ldquo;green&amp;rdquo; light). But so far what you&amp;rsquo;ve done is &lt;a
href="http://www.xprogramming.com/Practices/PracSimplest.html"&gt;&amp;ldquo;the
simplest thing that could possibly work&amp;rdquo;&lt;/a&gt; &amp;ndash; in other words,
you&amp;rsquo;ve been deliberately closely-focussed, overtly
short-termist, to get your tests to pass, and a refactoring stage is
needed to reintegrate your new functionality with the bigger
picture.&lt;/p&gt;

&lt;p&gt;Agile, of course, involves many of these cycles between project
start and project deadline, not just one. (Indeed, some say that each
cycle should be as small as &lt;a
href="http://www.infoq.com/news/2009/09/Pomodoro"&gt;a small
tomato&lt;/a&gt;. I find that the going rate is two small tomatoes to one
cup of tea.)  So the agile diagram isn&amp;rsquo;t drawn to quite the same
scale as the waterfall one: still, though, developers acquire the same
sense of schedule crunch, they skip on to the next task too soon, and
the corresponding failure mode occurs:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------+.....+
| Red           | Green         | Refac|
+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------------&lt;font color=red&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/font&gt;+------+.....+
^ Start                                ^ Deadline
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;The cause is the same, but what&amp;rsquo;s the effect? The code was
complete, and &amp;ndash; if not perfect &amp;ndash; then at least unit-tested, at the
end of the green phase. So the product as actually shipped works,
which is more than can be said for its waterfallen equivalent.&lt;/p&gt;

&lt;p&gt;All that&amp;rsquo;s missing, in fact, is some of the refactoring
effort. Unfortunately, that&amp;rsquo;s the only place in agile
development where any large-scale design work gets done: the &lt;a
href="http://c2.com/cgi/wiki?TechnicalDebt"&gt;design debt&lt;/a&gt; that an
agile shop takes out by not doing Big Design Up-Front, is paid off
only in these refactoring installments. This means that in fact the
effect of schedule crunch on agile projects, is that the system ends
up under-designed and directionless at any other than the lowest
level.&lt;/p&gt;

&lt;p&gt;And unlike the paper-bag obviousness of the waterfall model&amp;rsquo;s
failure mode, the agile model&amp;rsquo;s failure mode is subtle and
pernicious. Product 1.0 ships and works &amp;ndash; because agile development
&amp;ldquo;releases&amp;rdquo; every sprint, and thus is perfectly fitted for
triaging features against time. But the system is a &lt;a
href="http://en.wikipedia.org/wiki/Big_ball_of_mud"&gt;ball of
mud&lt;/a&gt;. Feature development on Product 1.5 and Product 2.0 takes
longer than expected &amp;ndash; which agile development also helps to hide,
given its stubborn reluctance to countenance long-term planning &amp;ndash;
because developers eventually spend all their time battling, not
intrinsic problems of the target domain, but incidental problems
caused by previous instances of themselves.&lt;/p&gt;

&lt;p&gt;Only the most obsessed &lt;em&gt;agiliste&lt;/em&gt; would claim that agile
development doesn&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; a failure mode. But because agile
development is new, its failure mode is unfamiliar to us; and because
that failure mode is less visibly catastrophic than Brooks&amp;rsquo;s, it&amp;rsquo;s
easier to overlook. It is, however, real; its very subtlety requires
us to pay particular care to look out for it, and to get right on top
of fixing it once we see it start to happen.&lt;/p&gt;

&lt;p&gt;Conversely, the fact that there &lt;em&gt;are&lt;/em&gt; problems that agile
development can&amp;rsquo;t solve, isn&amp;rsquo;t a fatal blow. Inevitably
such problems are the most visible ones &amp;ndash; because all the problems
which agile development &lt;em&gt;does&lt;/em&gt; solve easily, come and go
without anyone really noticing. And the failure mode of agile
development &amp;ndash; the system&amp;rsquo;s complexity spiralling out of
control &amp;ndash; can be fixed without doing too much damage to the
theory.&lt;/p&gt;

&lt;p&gt;And how to fix it? Schedule in some serious refactoring, one
subsystem at a time. In his paper &lt;em&gt;Checklist for Planning
Software System Production&lt;/em&gt;, RW Bemer, writing in August 1966
(&lt;em&gt;August 1966!&lt;/em&gt;) says:&lt;/p&gt;

&lt;table align=center&gt;&lt;tr&gt;&lt;td bgcolor=#eeeeee&gt;
&lt;table border=0&gt;
&lt;tr&gt;&lt;td align=left&gt;&lt;b&gt;Is periodic recoding recommended when a routine has lost a clean structural form?&lt;/b&gt;&lt;/td&gt;&lt;tr&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Nearly 45 years later, that&amp;rsquo;s still effectively the best
available advice. Whether you call it refactoring or periodic
recoding, it of course takes advantage of all the unit tests that the
ball of mud already contains. This time round, it also takes advantage
of knowledge about how all the parts of the subsystem operate. That
knowledge is unlikely to be acquired in a single two-week sprint, so
unless you can put someone on the task who already knows the subsystem
inside-out (and most of the time you&amp;rsquo;re in this state, there
won&amp;rsquo;t even &lt;em&gt;be&lt;/em&gt; such a person), you&amp;rsquo;ll find
yourselves breaking some of the rules of agile development by formally
or otherwise block-booking someone&amp;rsquo;s time for a larger
period. (Agile development aims at having any team member able to take
on any task in any sprint &amp;ndash; but for that to be okay, there
mustn&amp;rsquo;t be any software problems complex enough to require more
than two weeks&amp;rsquo; thought. Some software problems just are that
big, and context-switching can break the developers&amp;rsquo; train of
thought.)&lt;/p&gt;

&lt;p&gt;This is the answer to the sometimes-asked question, &amp;ldquo;If, in
agile development, everyone does design [as often as once per small
tomato], what&amp;rsquo;s the r&amp;ocirc;le of the architect?&amp;rdquo;. Agile
development is, in a way, &lt;a
href="http://www.amazon.co.uk/Timeless-Building-Center-Environmental-Structure/dp/0195024028"&gt;Christopher
Alexander&lt;/a&gt;&amp;rsquo;s observation that most things can be made
piecemeal. But simplicity cannot be made piecemeal. The contribution
of the software architect is simplicity.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-5412515248403922029?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/5412515248403922029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2011/04/failure-mode-of-agile-development.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/5412515248403922029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/5412515248403922029'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2011/04/failure-mode-of-agile-development.html' title='The Failure Mode Of Agile Development'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4726158073758434388</id><published>2011-01-22T22:45:00.009Z</published><updated>2011-04-09T22:57:51.440+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Is “Factory Method” An Anti-Pattern?</title><content type='html'>&lt;p&gt;Let&amp;rsquo;s take another look at this version of the &amp;ldquo;two
implementations, one interface&amp;rdquo; code from &lt;a
href="http://pdh11.blogspot.com/2010/05/portability-or-cut-and-paste.html"&gt;that
one about portability&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v8
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ~&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() {}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
  ...
};&lt;/FONT&gt;&lt;/B&gt;

std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;auto_ptr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; CreateEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;

// Event.cpp
&lt;/FONT&gt;&lt;/I&gt;std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;auto_ptr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; CreateEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;()
{
  ...&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF0000"&gt; return&lt;/FONT&gt; whichever derived&lt;FONT COLOR="#990000"&gt; class&lt;/FONT&gt; of Event is appropriate&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ...
}&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;What I didn&amp;rsquo;t say at the time is that this is sort-of the
Factory Method pattern, though a strict following of that pattern
would instead have us put the &lt;tt&gt;CreateEvent&lt;/tt&gt; function inside the
class as a static member, &lt;tt&gt;Event::Create()&lt;/tt&gt;. And the pattern
also includes designs where &lt;tt&gt;CreateEvent&lt;/tt&gt; is a factory method
on a different class from &lt;tt&gt;Event&lt;/tt&gt;, but it&amp;lsquo;s specifically
&amp;ldquo;self-factory methods&amp;rdquo; such as &lt;tt&gt;Event::Create&lt;/tt&gt; that
I&amp;rsquo;m concerned with here.&lt;/p&gt;

&lt;p&gt;(As an aside: the patterns literature comes in for a lot of
criticism for being simplistic. Which it is: the &lt;a
href="http://www.amazon.co.uk/Design-patterns-elements-reusable-object-oriented/dp/0201633612"&gt;GoF
book&lt;/a&gt; could be a quarter the size if it engaged in less
spoon-feeding and pedagoguery. (&lt;a
href="http://en.wikiquote.org/wiki/A_Bit_Of_Fry_And_Laurie#Episode_3"&gt;And
by pedagoguery I mean pedagoguery.&lt;/a&gt;) But in a sense the simplicity
and obviousness of the patterns they&amp;rsquo;re describing is the whole point:
thanks to the patternistas (patternauts?), a lot of simple and obvious
things that often come up in programmers&amp;rsquo; natural discourse about
code, and that didn&amp;rsquo;t previously have names, now do. Reading a
patterns book might not make your code much better unless you&amp;rsquo;re a
n00b, but that&amp;rsquo;s not what it&amp;rsquo;s &lt;i&gt;for&lt;/i&gt;. It&amp;rsquo;s for making your
&lt;i&gt;discourse about code&lt;/i&gt; better. In any n&amp;gt;1 team, being able to
discourse well about code is a vital skill.)&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QXt0fgMWRn8/TTtePI1oUBI/AAAAAAAAABw/x76JK46DmZE/s1600/21a.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 340px; height: 183px;" src="http://2.bp.blogspot.com/_QXt0fgMWRn8/TTtePI1oUBI/AAAAAAAAABw/x76JK46DmZE/s400/21a.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5565145378709852178" align="left" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what I also didn&amp;rsquo;t say at the time, is that whether
&lt;tt&gt;CreateEvent&lt;/tt&gt; is a member or not, so long as it&amp;rsquo;s in
&lt;tt&gt;event.h&lt;/tt&gt;, this code appears to have cyclic dependencies&amp;nbsp;&amp;mdash; to
be a violation of the principle of &amp;ldquo;levelisability&amp;rdquo; set
out in &lt;a
href="http://www.amazon.co.uk/Large-Scale-C-Software-Design-APC/dp/0201633620"&gt;the
Lakos book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s going on, as you can see on the left, is that,
although the source file dependencies themselves don&amp;rsquo;t exhibit
any cycles, viewing, as Lakos does, each header and its corresponding
&lt;tt&gt;.cpp&lt;/tt&gt; file as forming a &lt;i&gt;component&lt;/i&gt;&amp;nbsp;&amp;mdash; the
three grey rectangles&amp;nbsp;&amp;mdash; produces a component dependency
graph with cycles:
&lt;tt&gt;win32/event&lt;/tt&gt;&amp;nbsp;&amp;harr;&amp;nbsp;&lt;tt&gt;event&lt;/tt&gt;&amp;nbsp;&amp;harr;&amp;nbsp;&lt;tt&gt;posix/event&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QXt0fgMWRn8/TTtePlqmH2I/AAAAAAAAAB4/Ek2sO6k0DJU/s1600/21b.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 347px; height: 303px;" src="http://2.bp.blogspot.com/_QXt0fgMWRn8/TTtePlqmH2I/AAAAAAAAAB4/Ek2sO6k0DJU/s400/21b.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5565145386448199522"   align=right /&gt;&lt;/a&gt;
One way around
that would be to move CreateEvent out into its own
component&amp;nbsp;&amp;mdash; a freestanding event factory&amp;nbsp;&amp;mdash; as
seen on the right. With this change, the design is fairly clearly
levelisable at both the file level and the component level. This
refactoring is an example of what Lakos (5.2) calles
&lt;i&gt;escalation&lt;/i&gt;: knowledge of the multifarious nature of events has
been kicked upstairs to a higher-level class that, being higher-level,
is allowed to know everything. (The file &lt;tt&gt;event.cpp&lt;/tt&gt; now gets a
question-mark because, as the implementation file for what may now be
a completely abstract class, it might not exist at all&amp;nbsp;&amp;mdash; or
it might exist and contain the unit tests.)&lt;/p&gt;

&lt;p&gt;But is it worth it? We&amp;rsquo;ve arguably complicated the
code&amp;nbsp;&amp;mdash; requiring users of events to know also about event
factories&amp;nbsp;&amp;mdash; for what&amp;rsquo;s essentially the
&lt;i&gt;synthetic&lt;/i&gt; goal of levelisability: synthetic in the sense that
it won&amp;rsquo;t be appearing in any user-story. Any subsequent
programmer working on the code would be very tempted to fold the
factory back into &lt;tt&gt;event.h&lt;/tt&gt; under the banner of the Factory
Method pattern.&lt;/p&gt;

&lt;p&gt;Moreover, in this case the warning is basically a false positive:
if Event is truly an abstract class (give or take its factory method),
then the apparent coupling between, say, &lt;tt&gt;posix/event&lt;/tt&gt; and
&lt;tt&gt;event&lt;/tt&gt; is not in fact present: &lt;tt&gt;posix/event&lt;/tt&gt; can be
unit-tested without linking against &lt;tt&gt;event.o&lt;/tt&gt; nor
&lt;tt&gt;win32/event.o&lt;/tt&gt;. (Not that, in this particular example,
&lt;tt&gt;posix/event&lt;/tt&gt; and &lt;tt&gt;win32/event&lt;/tt&gt; would both exist for the
same target&amp;nbsp;&amp;mdash; but factory methods obviously also get used
for cases where both potential concrete products exist in the same
build.)  Though conversely, if &lt;tt&gt;Event&lt;/tt&gt; had any non-abstract
methods&amp;nbsp;&amp;mdash; any with implementations in
&lt;tt&gt;event.cpp&lt;/tt&gt;&amp;nbsp;&amp;mdash; then it&amp;rsquo;d be a true positive not
a false positive, as &lt;i&gt;all&lt;/i&gt; the different event types would be
undesirably link-time coupled together.&lt;/p&gt;

&lt;p&gt;One reason that the refactoring &lt;i&gt;is&lt;/i&gt; worth it, is the same
sort of reason that fixing compiler warnings, i.e. altering the code
so they don&amp;rsquo;t trigger, is worth it, even in instances when the warning
doesn&amp;rsquo;t point out a bug: because if you let warnings proliferate, real
ones will get lost in the noise, and ideally you aim for the
zero-warnings state in order that the introduction of &lt;i&gt;any&lt;/i&gt; new
warning is an easily-visible alert telling you that there&amp;rsquo;s a new
potential bug to check for. &lt;a
href="http://www.amazon.co.uk/Writing-Solid-Code-Techniques-Programming/dp/1556155514"&gt;Steve
Maguire&lt;/a&gt; is talking here about unit tests, but the same applies to
compiler warnings: &amp;ldquo;[W]hen they corner a bug, they grab it by the
antennae, drag it to the broadcast studio, and interrupt your
regularly-scheduled program&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Exactly like compiler warnings, cyclic-dependency
warnings&amp;nbsp;&amp;mdash; which are really design warnings&amp;nbsp;&amp;mdash;
are sometimes false positives, but likewise it&amp;rsquo;s worth aiming
for the &amp;ldquo;zero design warnings&amp;rdquo; state, because it makes new
design warnings stand out so. I ran a cycle-checker script (in the
spirit of the ones in Lakos) over my own &lt;a
href="http://chorale.sf.net"&gt;Chorale&lt;/a&gt; project, and the result was
that it effectively shone a spotlight on all the parts of the code
where the design was a bit icky. &lt;i&gt;Every&lt;/i&gt; cycle it
produced&amp;nbsp;&amp;mdash; one was
&lt;tt&gt;dvb::Service&lt;/tt&gt;&amp;nbsp;&amp;harr;&amp;nbsp;&lt;tt&gt;dvb::Recording&lt;/tt&gt;,
another was all the parts of &lt;tt&gt;db::steam&lt;/tt&gt; depending on each
other in a big loop&amp;nbsp;&amp;mdash; was a place where I&amp;rsquo;d at some
time thought, &amp;ldquo;Hmm, this isn&amp;rsquo;t quite right, but it works
for now and I&amp;rsquo;ll come back and do it properly&amp;rdquo;. And of
course without anything to remind me, I never had gone back and done
it properly.&lt;/p&gt;

&lt;p&gt;So it turns out that you can&amp;rsquo;t have both factory methods
&lt;i&gt;and&lt;/i&gt; levelisability. You have to pick one or the other. And
levelisability is better.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4726158073758434388?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4726158073758434388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2011/01/is-factory-method-anti-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4726158073758434388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4726158073758434388'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2011/01/is-factory-method-anti-pattern.html' title='Is “Factory Method” An Anti-Pattern?'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QXt0fgMWRn8/TTtePI1oUBI/AAAAAAAAABw/x76JK46DmZE/s72-c/21a.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-7592898269827287793</id><published>2010-10-06T20:53:00.001+01:00</published><updated>2010-10-06T21:28:32.207+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Quirking a Mac Pro into AHCI mode</title><content type='html'>&lt;p&gt;The Apple Mac Pro (2006 model) has an Intel &lt;sc&gt;ESB2&lt;/sc&gt;
south-bridge, which includes the &lt;sc&gt;SATA&lt;/sc&gt; controller. Under
MacOS, this &lt;sc&gt;SATA&lt;/sc&gt; controller is driven in &lt;sc&gt;AHCI&lt;/sc&gt; mode,
which is a great improvement on the &amp;ldquo;traditional IDE&amp;rdquo; mode
&amp;mdash; for one thing, it enables &amp;ldquo;NCQ&amp;rdquo; &lt;sc&gt;SCSI&lt;/sc&gt;-like
command queueing. But the pseudo-&lt;sc&gt;BIOS&lt;/sc&gt; that boots non-MacOS
operating systems on Intel Macs, forces the chip into traditional-IDE
mode. This is certainly a good idea for wide compatibility, but for an
OS which has &lt;sc&gt;AHCI&lt;/sc&gt; drivers &amp;mdash; such as Linux &amp;mdash;
it&amp;rsquo;d be good to force it back again.&lt;/p&gt;

&lt;p&gt;&lt;a
href="http://rants.atmurray.net/2009/06/sata-ahci-mode-on-systems-without-bios.html"&gt;Instructions
do exist&lt;/a&gt; for forcing it back again using a hacked Grub bootloader,
but for one thing that&amp;rsquo;s a hack, and for another I don&amp;rsquo;t
use Grub, I use Lilo. The &amp;ldquo;right&amp;rdquo; way (well, other than
convincing Apple to put an &lt;sc&gt;AHCI&lt;/sc&gt; mode into their
pseudo-&lt;sc&gt;BIOS&lt;/sc&gt;) is to use Linux&amp;rsquo;s &amp;ldquo;PCI quirk&amp;rdquo;
infrastructure. This patch (against 2.6.35.6, but similar should apply
almost anywhere) gives me toasty &lt;sc&gt;AHCI&lt;/sc&gt; goodness under
Linux:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
--- drivers/pci/quirks.c~ 2010-09-27 01:19:16.000000000 +0100
+++ drivers/pci/quirks.c 2010-10-06 20:29:04.000000000 +0100
@@ -1044,6 +1044,15 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDO
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
 
+static void __devinit quirk_intel_esb2_ahci(struct pci_dev *pdev)
+{
+    pci_write_config_byte(pdev, 0x90, 0x40);
+    pdev-&gt;class = PCI_CLASS_STORAGE_SATA_AHCI;
+    dev_info(&amp;amp;pdev-&gt;dev, "Intel ESB2 AHCI enabled\n");
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2680, quirk_intel_esb2_ahci);
+
 /*
  * Serverworks CSB5 IDE does not fully support native mode
  */
&lt;/pre&gt;&lt;/blockquote&gt;
And here it is in my dmesg:
&lt;blockquote&gt;&lt;pre&gt;
pci 0000:00:1f.2: Intel ESB2 AHCI enabled
ahci 0000:00:1f.2: flags: 64bit ncq pm led slum part 
ata1.00: 488397168 sectors, multi 16: LBA48 NCQ (depth 31/32)
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;All six &lt;sc&gt;SATA&lt;/sc&gt; ports (four for the drive carriers, two by
the optical drives) are seen by the &lt;tt&gt;ahci&lt;/tt&gt; driver (which I have
built-in to the kernel); loading the &lt;tt&gt;ata_piix&lt;/tt&gt; driver as a
module also enables the &lt;sc&gt;PATA&lt;/sc&gt; port by the optical
drives. (It's probably not a good idea to compile both &lt;tt&gt;ahci&lt;/tt&gt;
and &lt;tt&gt;ata_piix&lt;/tt&gt; into the kernel, in case they fight over the
&lt;sc&gt;ESB2&lt;/sc&gt; controller.)&lt;/p&gt;

&lt;p&gt;Job&amp;rsquo;s a good &amp;rsquo;un.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-7592898269827287793?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/7592898269827287793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2010/10/quirking-mac-pro-into-ahci-mode.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7592898269827287793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7592898269827287793'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2010/10/quirking-mac-pro-into-ahci-mode.html' title='Quirking a Mac Pro into AHCI mode'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-1101655078601506686</id><published>2010-05-31T01:22:00.000+01:00</published><updated>2010-05-31T01:24:11.194+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Portability, Or Cut-And-Paste?</title><content type='html'>&lt;p&gt;Suppose you&amp;rsquo;ve got some functionality with two completely different
implementations on different platforms:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v1
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // Win32 waitable event
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;

  void&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;m_hEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;
  Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() :&lt;/FONT&gt;&lt;/B&gt; m_hEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(::&lt;/FONT&gt;&lt;/B&gt;CreateEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;()) {}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;

  void&lt;/FONT&gt; Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

versus

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v2
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // Posix waitable event
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;
  int&lt;/FONT&gt; m_fd&lt;B&gt;&lt;FONT COLOR="#663300"&gt;[&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt;2&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;];&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;
  Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() { ::&lt;/FONT&gt;&lt;/B&gt;pipe&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;m_fd&lt;B&gt;&lt;FONT COLOR="#663300"&gt;); }&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // or maybe eventfd on Linux
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#FF6633"&gt;  void&lt;/FONT&gt; Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;And, by the way, if you&amp;rsquo;ve got a class where only &lt;i&gt;some&lt;/i&gt; of
the implementation is different on different platforms, you&amp;rsquo;ve first
got an opportunity for refactoring to extract that part of the
implementation as a self-contained class. Portability and
maintainability are aided if each of your classes is either wholly
portable, or wholly platform-specific. But as it is, you&amp;rsquo;ve got a more
immediate problem, which is that there&amp;rsquo;s two classes both called
Event, and any translation unit that includes both headers isn&amp;rsquo;t going
to compile. Here&amp;rsquo;s one solution:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v3
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#000099"&gt;#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif&lt;/FONT&gt;&lt;/pre&gt;&lt;/blockquote&gt;

This, plus its close relative

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v4
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#000099"&gt;#ifdef WIN32
#include "win32/Event.h"
#else
#include "posix/Event.h"
#endif&lt;/FONT&gt;&lt;/pre&gt;&lt;/blockquote&gt;

could well be the most commonly-encountered solutions to this problem
in real-world code. But they&amp;rsquo;re not without problems. One problem is
with code analysis tools, including such things as production of
automated documentation with Doxygen. Really you want such tools to
analyse your whole codebase, and if they do they&amp;rsquo;ll get hopelessly
confused with the two classes both called Event. (You can set up
preprocessor defines in Doxygen so that it only sees one Event class
-- but that only means the other doesn&amp;rsquo;t get documented, or that you
have two entire sets of Doxygen output for the two platforms, neither
of which sounds desirable.)&lt;/p&gt;

&lt;p&gt;To solve this problem, you&amp;rsquo;ve going to have to give the classes
different names:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v5
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Win32Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

class&lt;/FONT&gt; PosixEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;No, no, no, this is C++, there&amp;rsquo;s a built-in language facility
especially for namespaces, you don&amp;rsquo;t have to reinvent it in the class
names themselves:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v6
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // namespace win32
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;
namespace&lt;/FONT&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // namespace posix&lt;/FONT&gt;&lt;/I&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;(Why the comments on the &amp;ldquo;}&amp;rdquo; end-of-namespace lines?
Because the error messages you get from C++ when you accidentally miss
out an end-of-namespace brace are often insane and impenetrable,
especially if you do it in a header file, and it&amp;rsquo;s convenient to
be able to &lt;tt&gt;grep&amp;nbsp;namespace&amp;nbsp;*.h&amp;nbsp;*.cpp&lt;/tt&gt; and check
whether braces appear in matching pairs in the grep output.)&lt;/p&gt;

&lt;p&gt;Notice that both declarations are parsed on every compilation on
either platform. This might require you to move some method
definitions (those calling such unportable APIs as
&lt;tt&gt;::CreateEvent&lt;/tt&gt; and &lt;tt&gt;::pipe&lt;/tt&gt;) into a cpp file. But even
compiling the other platform&amp;rsquo;s declarations helps ensure that
changes on one platform won&amp;rsquo;t break the other platform without
somebody noticing. And a Doxygen run, or other automated code
analysis, will at least get to see both sets of declarations even if
not both sets of definitions.&lt;/p&gt;

&lt;p&gt;While going down the route of helping platform developers avoid
breaking other platforms, it&amp;rsquo;s been conspicuous so far that there&amp;rsquo;s
nothing in Event.h making sure that the Win32 and Posix
implementations keep the same API. Without such enforced consistency,
there&amp;rsquo;s a risk of client code unwittingly using non-portable APIs. The
way to enforce the consistency, of course, is to derive from an
abstract base class containing the API:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v7
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; EventAPI&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ~&lt;/FONT&gt;&lt;/B&gt;EventAPI&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() {}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

namespace&lt;/FONT&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; EventAPI&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // namespace win32
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;
namespace&lt;/FONT&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; EventAPI&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
  ...
};
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt; // namespace posix&lt;/FONT&gt;&lt;/I&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;This is, after all, exactly the sort of thing you&amp;rsquo;d do if you
had two different sorts of Event that were both used in the
&lt;i&gt;same&lt;/i&gt; build of the program. Really the fact that no one
individual binary will contain instances of both classes,
doesn&amp;rsquo;t mean that the quest for well-factored design should be
thrown out of the window and replaced with cut-and-paste.&lt;/p&gt;

&lt;p&gt;Now, though, all the method calls have become virtual function
calls. For most of any given codebase, that won&amp;rsquo;t matter, but
there&amp;rsquo;ll always be hot paths and/or embedded systems where it
does, and indeed an event class might quite plausibly be on such a
critical path. And after all, compiling the client code itself
provides a, potentially large, body of checks that the API has
remained consistent over time. It&amp;rsquo;s reasonable to adopt the
position that using design techniques to discourage unthinkingly
changing core APIs in a non-portable way isn&amp;rsquo;t actually
necessary, so long as the compilation-failure results of such a change
are always speedily available from all target platforms, such as from
an automated-build or continuous-integration system.&lt;/p&gt;

&lt;p&gt;If, conversely, your class is only used in situations where
nobody&amp;rsquo;s really counting individual machine cycles, you could
hide the implementations altogether, at the cost of ruling out stack
objects and member variables of type Event and requiring a heap
(&lt;tt&gt;new&lt;/tt&gt;) allocation every time one is created:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v8
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ~&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() {}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
  virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
  ...
};&lt;/FONT&gt;&lt;/B&gt;

std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;auto_ptr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; CreateEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;

// Event.cpp
&lt;/FONT&gt;&lt;/I&gt;std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;auto_ptr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; CreateEvent&lt;B&gt;&lt;FONT COLOR="#663300"&gt;()
{
  ...&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF0000"&gt; return&lt;/FONT&gt; whichever derived&lt;FONT COLOR="#990000"&gt; class&lt;/FONT&gt; of Event is appropriate&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ...
}&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;But for now let&amp;rsquo;s assume you can&amp;rsquo;t really conceal the
two platform-specific declarations, and go back to Event.h version 6
or version 7. Let&amp;rsquo;s look at how client code gets to pick which
of the two implementations it uses. For a start, not like this:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; NominallyPortableDomainAbstraction&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#ifdef WIN32
&lt;/FONT&gt;  win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event m_event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;  posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event m_event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif
&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;  ...&lt;/FONT&gt;&lt;/B&gt;
  m_event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;.&lt;/FONT&gt;&lt;/B&gt;Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Flouting our design rule that each class is either wholly portable
or wholly platform-specific, this sort of thing couples portability
decisions into all client code, which is very undesirable. This is
much better:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v9
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;...&lt;/FONT&gt;&lt;/B&gt; as before in v6&lt;B&gt;&lt;FONT COLOR="#663300"&gt; or&lt;/FONT&gt;&lt;/B&gt; v7&lt;FONT COLOR="#000099"&gt;

#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;typedef&lt;/FONT&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;typedef&lt;/FONT&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif
&lt;/FONT&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;
// Client code
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; NominallyPortableDomainAbstraction&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{&lt;/FONT&gt;&lt;/B&gt;
  Event m_event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
  ...&lt;/FONT&gt;&lt;/B&gt;
  m_event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;.&lt;/FONT&gt;&lt;/B&gt;Wake&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();
  ...
};&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;It&amp;rsquo;s still not great, though: if there are lots of classes
involved, lots of code ends up inside the &lt;tt&gt;#ifdef&lt;/tt&gt;s. How can we
minimise the amount of &lt;tt&gt;#ifdef&lt;/tt&gt;&amp;rsquo;d code? Well,
here&amp;rsquo;s one way:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v10
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;...&lt;/FONT&gt;&lt;/B&gt; as before in v6&lt;B&gt;&lt;FONT COLOR="#663300"&gt; or&lt;/FONT&gt;&lt;/B&gt; v7&lt;FONT COLOR="#000099"&gt;

#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;using namespace&lt;/FONT&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;using namespace&lt;/FONT&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif&lt;/FONT&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;But this, of course, introduces everything from those namespaces
into the surrounding namespace. Not only is that namespace pollution,
it&amp;rsquo;s potentially misleading for client code, as there may be
Win32-specific classes or functions -- ones with no Posix equivalent,
for use in Win32 situations only -- which are now accessible in
portable code without the telltale &lt;tt&gt;win32::&lt;/tt&gt; prefix. (And, of course,
vice versa for Posix-specific ones.) Really we want to explicitly
enumerate which classes and APIs are intended to be portable. So we
can do this:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v11
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;...&lt;/FONT&gt;&lt;/B&gt; as before in v6&lt;B&gt;&lt;FONT COLOR="#663300"&gt; or&lt;/FONT&gt;&lt;/B&gt; v7&lt;FONT COLOR="#000099"&gt;

#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; platform&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; platform&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;
using&lt;/FONT&gt; platform&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
using&lt;/FONT&gt; platform&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;PollThread&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
...&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;The intention is that the &lt;tt&gt;using&lt;/tt&gt; declarations list
precisely those facilities which are available on all platforms, but
with differing implementations on each. Non-portable classes or
functions can stay in namespace win32 (or namespace posix) so that any
use of them in client code immediately flags that code up as itself
non-portable.&lt;/p&gt;

&lt;p&gt;There is one problem with this neat solution, though: it
doesn&amp;rsquo;t actually compile. Or rather, once you do the same thing
in several different header files, you&amp;rsquo;ll find that multiple
&lt;tt&gt;namespace&amp;nbsp;X&amp;nbsp;=&amp;nbsp;Y;&lt;/tt&gt; statements for the same
namespace X aren&amp;rsquo;t allowed, even if Y is the same each time. So,
sadly, you have to come up with a different name for
&amp;ldquo;platform&amp;rdquo; each time (or centralise the &lt;tt&gt;using&lt;/tt&gt; in
one header file, causing potentially-undesirable widespread dependency
on that file):&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v12
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;...&lt;/FONT&gt;&lt;/B&gt; as before in v6&lt;B&gt;&lt;FONT COLOR="#663300"&gt; or&lt;/FONT&gt;&lt;/B&gt; v7&lt;FONT COLOR="#000099"&gt;

#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;
using&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
using&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;PollThread&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
...&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;There&amp;rsquo;s only one remaining wrinkle, which is that you
can&amp;rsquo;t forward-declare a class-name if that name only exists due
to &lt;tt&gt;using&lt;/tt&gt;. So if there are header files that traffic in
&lt;tt&gt;Event*&lt;/tt&gt; or &lt;tt&gt;Event&amp;amp;&lt;/tt&gt; and could otherwise be
satisfied with a forward declaration &lt;tt&gt;class Event;&lt;/tt&gt; and avoid
including Event.h, then you can&amp;rsquo;t use Event.h version
12. (Version 9 is also out, as you can&amp;rsquo;t forward-declare
typedefs either.) The best you can do is probably this:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;I&gt;&lt;FONT COLOR="#444444"&gt;// Event.h v13
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;...&lt;/FONT&gt;&lt;/B&gt; as before in v6&lt;B&gt;&lt;FONT COLOR="#663300"&gt; or&lt;/FONT&gt;&lt;/B&gt; v7&lt;FONT COLOR="#000099"&gt;

#ifdef WIN32
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; win32&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#else
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;namespace&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; posix&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#000099"&gt;
#endif
&lt;/FONT&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Event&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
class&lt;/FONT&gt; PollThread&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; eventimpl&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;PollThread&lt;B&gt;&lt;FONT COLOR="#663300"&gt; {};
...&lt;/FONT&gt;&lt;/B&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;although naturally that only works as-written if the
&lt;tt&gt;eventimpl&lt;/tt&gt; base classes don&amp;rsquo;t have constructors other
than the default constructor; if they did, you&amp;rsquo;d have to write
forwarding constructors in each derived class, making the code a lot
less neat.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-1101655078601506686?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/1101655078601506686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2010/05/portability-or-cut-and-paste.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/1101655078601506686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/1101655078601506686'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2010/05/portability-or-cut-and-paste.html' title='Portability, Or Cut-And-Paste?'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-7570857093036249651</id><published>2010-05-26T20:25:00.003+01:00</published><updated>2010-05-31T01:24:55.301+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Think Same: Mapping An Apple Keyboard Like It’s A Normal One</title><content type='html'>&lt;p&gt;The aluminium &amp;ldquo;laptop-style&amp;rdquo; Apple keyboards are really
nice: quick and easy to type on. I&amp;rsquo;ve got one on my main Linux
machine. But they&amp;rsquo;re mapped oddly (or at least the UK one is):
backtick is next to Z, and backslash next to Enter. As I&amp;rsquo;m
usually watching the screen and not the keyboard while typing, the
fact that these think-different mappings are borne out by the printing
on the keycaps doesn&amp;rsquo;t help.&lt;/p&gt;

&lt;p&gt;So I needed to swap them back again. And, X being the stovepipe it
is, I needed to do it twice, once for inside X (including Gnome and
KDE) and once for the console.&lt;/p&gt;

&lt;p&gt;X was actually easier: I added this to &lt;tt&gt;~/.xinitrc&lt;/tt&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;tt&gt;# Apple silver keyboard has these keycodes swapped&lt;br&gt;
xmodmap -e "keycode 94 = grave notsign grave notsign bar bar"&lt;br&gt;
xmodmap -e "keycode 49 = backslash bar backslash bar bar brokenbar"&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;For console use there doesn&amp;rsquo;t seem to be a similar way of
modifying just certain keycodes, so you end up needing to make a whole
new keymap:&lt;/p&gt;

&lt;blockquote&gt;
&lt;tt&gt;dumpkeys &amp;gt; keymap.txt&lt;/tt&gt;&lt;br&gt;
&lt;i&gt;(edit keymap.txt)&lt;/i&gt;&lt;br&gt;
&lt;tt&gt;loadkeys &lt; keymap.txt&lt;/tt&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here&amp;rsquo;s the diff I had to apply to the standard UK map to get
the Apple keyboard working the way my fingers expect:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;--- std_keymap  2010-03-12 13:49:34.000000000 +0000
+++ silverapple.keymap  2010-03-12 13:50:39.000000000 +0000
@@ -93,9 +93,9 @@
        shift   control keycode  40 = nul             
        alt     keycode  40 = Meta_apostrophe 
        shift   alt     keycode  40 = Meta_at         
-keycode  41 = grave            notsign          bar              nul             
-       alt     keycode  41 = Meta_grave      
-       control alt     keycode  41 = Meta_nul        
+keycode  86 = grave            notsign          bar              nul             
+       alt     keycode  86 = Meta_grave      
+       control alt     keycode  86 = Meta_nul        
 keycode  42 = Shift           
 keycode  43 = numbersign       asciitilde      
        control keycode  43 = Control_backslash
@@ -201,10 +201,10 @@
        control alt     keycode  83 = Boot            
 keycode  84 = Last_Console    
 keycode  85 =
-keycode  86 = backslash        bar              bar              Control_backslash
-       alt     keycode  86 = Meta_backslash  
-       shift   alt     keycode  86 = Meta_bar        
-       control alt     keycode  86 = Meta_Control_backslash
+keycode  41 = backslash        bar              bar              Control_backslash
+       alt     keycode  41 = Meta_backslash  
+       shift   alt     keycode  41 = Meta_bar        
+       control alt     keycode  41 = Meta_Control_backslash
 keycode  87 = F11              F23              Console_23       F35             
        alt     keycode  87 = Console_11      
        control alt     keycode  87 = Console_11&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;And to get this loaded on every boot, I stuck it in /etc/rc.local:

&lt;blockquote&gt;&lt;pre&gt;# Apple keyboards start up in "F-keys are magic" mode; this puts them in
# "F-keys are F-keys" mode
echo 2 &amp;gt; /sys/module/hid_apple/parameters/fnmode

# Also they have the backslash and backtick keys swapped
loadkeys &amp;lt; /etc/silverapple.keymap
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Oh, right, yes, the function keys: they think different too, or at
least they default to think-different mode on power-up. To get them
thinking same, you need to have the Linux &lt;tt&gt;hid_apple&lt;/tt&gt; module
loaded, and to set its &amp;ldquo;fnmode&amp;rdquo; parameter as above. (Other
systems may use &lt;a
href="https://help.ubuntu.com/community/AppleKeyboard"&gt;other ways&lt;/a&gt;
of setting module parameters.)&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;ve found this and want to check that your fingers are
mapped the same way mine are, this is the list of keys that, with the
setup above, do not generate the symbol printed on the keycap:

&lt;table border align=center&gt;&lt;tr&gt;&lt;td&gt;&lt;i&gt;labelled&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;generates&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;sect;&lt;/td&gt;&lt;td&gt;` (backtick)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;plusmn; (shift-&amp;sect;)&lt;/td&gt;&lt;td&gt;&amp;not; (notsign)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;@ (shift-2)&lt;/td&gt;&lt;td&gt;"&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;" (shift-')&lt;/td&gt;&lt;td&gt;@&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;\&lt;/td&gt;&lt;td&gt;#&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;| (shift-\)&lt;/td&gt;&lt;td&gt;~&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;` (backtick)&lt;/td&gt;&lt;td&gt;\&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;~ (shift-`)&lt;/td&gt;&lt;td&gt;|&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Overall you lose the ability to type &amp;ldquo;&amp;sect;&amp;rdquo; and
&amp;ldquo;&amp;plusmn;&amp;rdquo;, and gain &amp;ldquo;&amp;not;&amp;rdquo; (meh) and, rather
surprisingly, the hash character &amp;ldquo;#&amp;rdquo;, which isn&amp;rsquo;t
marked anywhere on the Apple keyboard.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-7570857093036249651?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/7570857093036249651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2010/05/think-same-mapping-apple-keyboard-like.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7570857093036249651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7570857093036249651'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2010/05/think-same-mapping-apple-keyboard-like.html' title='Think Same: Mapping An Apple Keyboard Like It&amp;rsquo;s A Normal One'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-7929964909364460152</id><published>2010-01-31T21:24:00.000Z</published><updated>2010-01-31T21:25:21.435Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>How Facebook Wasted An Hour And A Half Of My Life</title><content type='html'>&lt;p&gt;Now it should be admitted up-front that in fact, taken as a whole,
Facebook has in fact wasted far more than an hour and a half of my
life. But all the other hours and halves, I at least felt it was my
choice to waste them. This time, however, it was
definitely Facebook&amp;rsquo;s
choice instead &amp;mdash; or Apple&amp;rsquo;s.
&lt;/p&gt;

&lt;p&gt;The problem started when Facebook for Iphone refused to do
anything, showing only the message &amp;ldquo;This version of the Facebook
application is no longer supported. Please upgrade to version
3.0.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Despite having always thought that the whole point of web
applications, or websites in general, is that you design them
carefully-enough to start with that you can support old URLs or
clients in the field indefinitely &amp;mdash; you can&amp;rsquo;t, after all,
reach out and rewrite everyone in the world&amp;rsquo;s bookmark files if
you want to change a URL &amp;mdash; I consoled myself that at least
updates to Facebook for Iphone are free, so went off to the Iphone App
Store to download the newer version. But that failed too: apparently
version 3.0 of Facebook for Iphone required at least Iphone OS 3.0,
and mine was still on 2.2.&lt;/p&gt;

&lt;p&gt;Upgrading the OS on a jailbroken Iphone &lt;a
href="http://xkcd.com/349/"&gt;can be stressful&lt;/a&gt;, but I thought that,
as Facebook was pretty much the only Iphone application I actually
used, even the worse-case scenario of bricking the phone and going
back to the Nokia 8890 wouldn&amp;rsquo;t lose me that much. It turns out
that the procedure for upgrading a jailbroken Iphone to OS&amp;nbsp;3.1.2
is as follows:&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;b&gt;Find out &lt;a
href="http://www.iclarified.com/entry/index.php?enid=4255"&gt;how&lt;/a&gt;.&lt;/b&gt; I&amp;rsquo;m
not even including the finding in the hour and a half.

&lt;li&gt;&lt;b&gt;Reboot,&lt;/b&gt; because it only works from MacOS.

&lt;li&gt;&lt;b&gt;Download&lt;/b&gt; Pwnagetool, BL-3.9, and the IPSW. (I always think
that the file icon for IPSW files ought to be &lt;a
href="http://en.wikipedia.org/wiki/Ipswich_town"&gt;a blue scarf&lt;/a&gt;, but
it isn&amp;rsquo;t.)

&lt;li&gt;&lt;b&gt;Try&lt;/b&gt; and download BL-4.6, but the link doesn&amp;rsquo;t work.

&lt;li&gt;&lt;b&gt;Go and fetch&lt;/b&gt; BL-4.6 on a USB stick from the Windows laptop
you last did an Iphone upgrade from. (This is actually an improvement
over the previous process, which only lets you know you&amp;rsquo;ll need the BL
files halfway through the upgrade itself.)

&lt;li&gt;&lt;b&gt;Run Pwnagetool&lt;/b&gt;, which immediately stops because you need at
least Itunes 8 for the &amp;ldquo;restore from specific IPSW&amp;rdquo; feature, and you
only have Itunes 7.

&lt;li&gt;&lt;b&gt;In Itunes, run &amp;ldquo;Check for updates&amp;rdquo;&lt;/b&gt;, which runs the system
Software Updater program, which offers loads of nonsense. Untick
everything except Itunes, and download and install it.

&lt;li&gt;&lt;b&gt;Run Pwnagetool again&lt;/b&gt;, which now does everything it needs to
and creates the custom IPSW.

&lt;li&gt;&lt;b&gt;Put the Iphone into recovery mode.&lt;/b&gt;

&lt;li&gt;&lt;b&gt;Run Itunes&lt;/b&gt;, which refuses to start because it needs
Quicktime 7.5.5 or later.

&lt;li&gt;&lt;b&gt;Go and find Software Updater&lt;/b&gt; (it&amp;rsquo;s in System Preferences)
and run it again. Untick everything except Quicktime, and download and
install it.

&lt;li&gt;&lt;b&gt;Reboot&lt;/b&gt;, because the Quicktime installer demands it.

&lt;li&gt;&lt;b&gt;Put the Iphone into recovery mode again&lt;/b&gt; because it&amp;rsquo;s fallen
out of it during the reboot.

&lt;li&gt;&lt;b&gt;Re-run Itunes&lt;/b&gt;, and have it tell you &amp;ldquo;Itunes could not
contact the Iphone software update server because you are not
connected to the internet.&amp;rdquo;

&lt;li&gt;&lt;b&gt;Click on &amp;ldquo;More information&amp;rdquo;&lt;/b&gt; about this &amp;ldquo;no internet&amp;rdquo; error,
and watch it open a &lt;i&gt;web page&lt;/i&gt; in Firefox to tell you about it.

&lt;li&gt;&lt;b&gt;Start to wonder&lt;/b&gt; whether Apple are just deliberately messing
with your head in order to scold you for jailbreaking their phone.

&lt;li&gt;&lt;b&gt;Unplug the network cable&lt;/b&gt; from the Mac and plug it directly
into the router, bypassing the HTTP proxy.

&lt;li&gt;&lt;b&gt;Reconfigure&lt;/b&gt; both MacOS and Firefox not to use the proxy.

&lt;li&gt;&lt;b&gt;Quit and re-run Itunes,&lt;/b&gt; because there&amp;rsquo;s no obvious
way of telling it to rescan for devices.

&lt;li&gt;&lt;b&gt;Actually install the upgrade,&lt;/b&gt; which takes ages to
&amp;ldquo;prepare&amp;rdquo;, much of which time you spend eyeing the old Nokia 8890
which never caused you any of these problems.

&lt;li&gt;&lt;b&gt;Once the Iphone restarts,&lt;/b&gt; observe with relief the little
magnifying-glass icon that 2.2 didn&amp;rsquo;t have, thus providing evidence
that the upgrade actually did something. Also notice that it&amp;rsquo;s
rearranged all your icons; arrange them back the way you like.

&lt;li&gt;&lt;b&gt;Install&lt;/b&gt; the Facebook application from the Iphone App Store.

&lt;li&gt;&lt;b&gt;Open &amp;ldquo;Contacts&amp;rdquo;&lt;/b&gt; and realise that in fact the upgrade has
wiped all your user data.

&lt;li&gt;&lt;b&gt;Notice with relief&lt;/b&gt; that Itunes is now asking you whether to
restore the Iphone from a backup.

&lt;li&gt;&lt;b&gt;Notice with alarm&lt;/b&gt; that the backup in question is from 2008.

&lt;li&gt;&lt;b&gt;Restore from the backup&lt;/b&gt; anyway because it&amp;rsquo;s got to be
better than nothing.

&lt;li&gt;&lt;b&gt;Rearrange all your icons&lt;/b&gt; back the way you like them again.

&lt;li&gt;&lt;b&gt;Reinstall&lt;/b&gt; the Facebook application from the Iphone App
Store, because the restore restored the old version.

&lt;li&gt;&lt;b&gt;Unplug the network cable&lt;/b&gt; again and plug the Mac in back
behind the firewall where it belongs.

&lt;li&gt;&lt;b&gt;Reboot&lt;/b&gt; back into Linux.

&lt;li&gt;&lt;b&gt;Start wondering&lt;/b&gt; what important phone numbers you&amp;rsquo;ve
obtained since 2008.

&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-7929964909364460152?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/7929964909364460152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2010/01/how-facebook-wasted-hour-and-half-of-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7929964909364460152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7929964909364460152'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2010/01/how-facebook-wasted-hour-and-half-of-my.html' title='How Facebook Wasted An Hour And A Half Of My Life'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4645403140173980051</id><published>2009-11-16T15:42:00.001Z</published><updated>2009-11-16T15:43:21.984Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>This Code Is Completely Bogus</title><content type='html'>&lt;p&gt;Here&amp;rsquo;s some rubbish code I wrote:&lt;/p&gt;
&lt;blockquote&gt;&lt;PRE&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; util&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Stream&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
    ...&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    class&lt;/FONT&gt; Observer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
    {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
 virtual&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ~&lt;/FONT&gt;&lt;/B&gt;Observer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() {}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

 virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; unsigned&lt;/FONT&gt; OnHttpHeader&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; key&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
          const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; value&lt;B&gt;&lt;FONT COLOR="#663300"&gt;) =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
 virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; unsigned&lt;/FONT&gt; OnHttpData&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
 virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; OnHttpDone&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;unsigned int&lt;/FONT&gt; error_code&lt;B&gt;&lt;FONT COLOR="#663300"&gt;) =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
    };&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

private&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    explicit&lt;/FONT&gt; Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;Observer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;*);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    friend class&lt;/FONT&gt; Client&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:
    ~&lt;/FONT&gt;&lt;/B&gt;Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;

    unsigned int&lt;/FONT&gt; OnActivity&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    // Being a Stream
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#FF6633"&gt;    unsigned&lt;/FONT&gt; Read&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;void&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;buffer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt; size_t len&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt; size_t&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;pread&lt;B&gt;&lt;FONT COLOR="#663300"&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;
    unsigned&lt;/FONT&gt; Write&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;const&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *,&lt;/FONT&gt;&lt;/B&gt; size_t&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt; size_t&lt;B&gt;&lt;FONT COLOR="#663300"&gt;*) {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF0000"&gt; return&lt;/FONT&gt; EINVAL&lt;B&gt;&lt;FONT COLOR="#663300"&gt;; }
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

typedef&lt;/FONT&gt; boost&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;intrusive_ptr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; ConnectionPtr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

class&lt;/FONT&gt; Client&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;
    Client&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Passing a NULL verb means POST (if !body.empty()) or GET (otherwise).
     */&lt;/FONT&gt;&lt;/I&gt;
    ConnectionPtr Connect&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;util&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;PollerInterface&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;poller&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;
     Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Observer&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;obs&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
     const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; url&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
     const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; extra_headers&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(),&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
     const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; body&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(),&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
     const&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; char&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;verb&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; NULL&lt;B&gt;&lt;FONT COLOR="#663300"&gt;);
};&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s meant to be an &lt;sc&gt;HTTP&lt;/sc&gt; client implementation,
where the &lt;tt&gt;Connect()&lt;/tt&gt; call returns a &lt;a
href="http://en.wikipedia.org/wiki/Smart_pointer"&gt;smart pointer&lt;/a&gt; to
a connection object that manages its own lifetime. The
&lt;tt&gt;Connect()&lt;/tt&gt; call sets it all off, and attaches it to the &lt;tt&gt;&lt;a
href="http://www.cl.cam.ac.uk/cgi-bin/manpage?2+poll"&gt;Poll&lt;/a&gt;erInterface&lt;/tt&gt;
object, which calls back into the &lt;tt&gt;Connection&lt;/tt&gt; object (the
&lt;tt&gt;OnActivity&lt;/tt&gt; method) whenever the socket becomes writable (or
readable, depending on where we are in the &lt;sc&gt;http&lt;/sc&gt;
transaction).&lt;/p&gt;

&lt;p&gt;I mean, just look at it: it&amp;rsquo;s obviously completely bogus. [Short
pause whilst you just look at it.]&lt;/p&gt;

&lt;p&gt;Actually, no. It wasn&amp;rsquo;t at all obvious to me just from looking at
it, that it was completely bogus. The only point, in fact, at which it
became obvious that it was completely bogus, was when it started
causing bugs.&lt;/p&gt;

&lt;p&gt;And the bugs it caused were quite awkward ones: crashes (and &lt;a
href="http://www.valgrind.org/"&gt;Valgrind&lt;/a&gt; violations), obviously
timing-related, to do somehow with &lt;tt&gt;Connection&lt;/tt&gt; pointers still being
used after the object had gone away &amp;mdash; which should really have been
disallowed by the smart-pointer class.&lt;/p&gt;

&lt;p&gt;It turned out that the problem was if the transaction completed
&lt;em&gt;too quickly&lt;/em&gt;. At the time the code was written, the
&lt;tt&gt;PollerInterface&lt;/tt&gt; object didn&amp;rsquo;t own (smart pointers to) the
pollable items hung off it. So, in order to stop the
&lt;tt&gt;Connection&lt;/tt&gt; object disappearing, due to the final reference
going away, &lt;em&gt;during&lt;/em&gt; a call to &lt;tt&gt;OnActivity&lt;/tt&gt;,
&lt;tt&gt;OnActivity&lt;/tt&gt; itself creates and holds an additional reference
to the &lt;tt&gt;Connection&lt;/tt&gt; object during its execution. But if the
transaction got started quickly enough, the first call to
&lt;tt&gt;OnActivity&lt;/tt&gt; would happen before the constructor returned &amp;mdash; in
other words, before the pointer had been assigned to the smart-pointer
that&amp;rsquo;s the result of &lt;tt&gt;Connect()&lt;/tt&gt;. So the &amp;ldquo;additional&amp;rdquo; reference
held inside &lt;tt&gt;OnActivity&lt;/tt&gt; would be the &lt;em&gt;only&lt;/em&gt; reference
&amp;mdash; and when it went away at the end of the function, there&amp;rsquo;d be no
outstanding references and the object would be deleted.&lt;/p&gt;

&lt;p&gt;The effect was as if the constructor had included &amp;ldquo;&lt;tt&gt;delete
this&lt;/tt&gt;&amp;rdquo; &amp;mdash; resulting in the &lt;tt&gt;new&lt;/tt&gt; call in &amp;ldquo;&lt;tt&gt;p = new
Connection&lt;/tt&gt;&amp;rdquo; returning a pointer that was &lt;em&gt;already&lt;/em&gt; dead
and dangling before even being assigned to &lt;tt&gt;p&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;Completely bogus. And worse, a completely bogus &lt;em&gt;design&lt;/em&gt;;
given the constraints, there was nothing that could possibly be done
in the methods of the classes &lt;tt&gt;Client&lt;/tt&gt; and &lt;tt&gt;Connection&lt;/tt&gt;
that would correctly implement that interface. The interface itself
needed to change. Fortunately, I decided it didn&amp;rsquo;t need to change
&lt;em&gt;much&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{
    ...&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Start the HTTP transaction.
     *
     * Immediate errors (failure to parse host, failure of connect()
     * call) are returned here; errors happening any later come back
     * through Observer::OnHttpDone. In fact, OnHttpDone may be called
     * before Init() returns, i.e. you need to be ready for OnHttpDone
     * calls before you call Init(). If Init() returns a failure,
     * OnHttpDone has not been called, and is guaranteed not to be
     * called afterwards. Otherwise, it's guaranteed it WILL be
     * called.
     */&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#FF6633"&gt;
    unsigned int&lt;/FONT&gt; Init&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();
    ...
};&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So you get a completely inert &lt;tt&gt;ConnectionPtr&lt;/tt&gt; back from
&lt;tt&gt;Client::Connect&lt;/tt&gt;, and only then &amp;mdash; once you&amp;rsquo;ve safely
squirreled-away the smart-pointer &amp;mdash; do you light the blue touch-paper
by calling &lt;tt&gt;Connection::Init()&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;But although this version at least makes it &lt;em&gt;possible&lt;/em&gt; to
use the functionality correctly, it doesn&amp;rsquo;t really make it
&lt;em&gt;easy&lt;/em&gt; &amp;mdash; and that should be the real goal of any act of API
design. There&amp;rsquo;s that uneasy division of labour between
&lt;tt&gt;Connect()&lt;/tt&gt; and &lt;tt&gt;Init()&lt;/tt&gt; &amp;mdash; methods on two different
classes &amp;mdash; and there&amp;rsquo;s a whole paragraph of complex object-lifetime
issues to read and understand (or, as they&amp;rsquo;re otherwise known,
&lt;em&gt;bugs waiting to happen&lt;/em&gt;) for users of &lt;tt&gt;Init()&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;This, and particularly the lifetime of the
&lt;tt&gt;Connection::Observer&lt;/tt&gt; object, which usually ends up having to
call &amp;ldquo;&lt;tt&gt;delete this&lt;/tt&gt;&amp;rdquo; in its &lt;tt&gt;OnHttpDone()&lt;/tt&gt; method, left
me with one of those code itches that tells me that I (and, the
largely theoretical, other users of this API) am writing more complex
and icky client code than I should be.&lt;/p&gt;

&lt;p&gt;Neatening this up required making the object-lifetime issues more
sane, which in turn involved greater use of smart pointers. (Not quite
&lt;a
href="http://en.wikipedia.org/wiki/David_Wheeler_%28computer_scientist%29"&gt;Wheeler&lt;/a&gt;&amp;rsquo;s
Law, because there was already a use of indirection, and the change
involved only a strengthening from reference to ownership.) In the
next release of Chorale, the &lt;tt&gt;PollerInterface&lt;/tt&gt; has been
replaced by a &lt;tt&gt;Scheduler&lt;/tt&gt;, which keeps smart pointers to its
pollable items, allowing the &lt;sc&gt;HTTP&lt;/sc&gt; client API to be simplified to
this:&lt;/p&gt;

&lt;blockquote&gt;&lt;PRE&gt;&lt;FONT COLOR="#990000"&gt;class&lt;/FONT&gt; Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; public&lt;/FONT&gt; util&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Stream&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    virtual&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; ~&lt;/FONT&gt;&lt;/B&gt;Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;() {}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Called with data from the returned HTTP body (if transaction
     * succeeds).
     */&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;
    virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; unsigned&lt;/FONT&gt; Write&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;const&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;buffer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt; size_t len&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt; size_t&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;pwrote&lt;B&gt;&lt;FONT COLOR="#663300"&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Called with each incoming HTTP header (if connection succeeds).
     */&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;
    virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; OnHeader&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt; /*key*/&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt; 
     const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt; /*value*/&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;) {}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Called with the overall result of the connection/transaction attempt.
     */&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#990000"&gt;
    virtual&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; void&lt;/FONT&gt; OnDone&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#FF6633"&gt;unsigned int&lt;/FONT&gt; error_code&lt;B&gt;&lt;FONT COLOR="#663300"&gt;) =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#999900"&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;
};&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

typedef&lt;/FONT&gt; util&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;CountedPointer&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;Connection&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt; ConnectionPtr&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

class&lt;/FONT&gt; Client&lt;B&gt;&lt;FONT COLOR="#663300"&gt;
{&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    class&lt;/FONT&gt; Task&lt;B&gt;&lt;FONT COLOR="#663300"&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;

public&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt;:&lt;/FONT&gt;&lt;/B&gt;
    Client&lt;B&gt;&lt;FONT COLOR="#663300"&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT COLOR="#999999"&gt;

    /** Passing a NULL verb means POST (if body != NULL) or GET (otherwise).
     */&lt;/FONT&gt;&lt;/I&gt;&lt;FONT COLOR="#FF6633"&gt;
    unsigned int&lt;/FONT&gt; Connect&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(&lt;/FONT&gt;&lt;/B&gt;util&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;Scheduler&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;poller&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;
    ConnectionPtr target&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; url&lt;B&gt;&lt;FONT COLOR="#663300"&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; extra_headers&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(),&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    const&lt;/FONT&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;&amp;amp;&lt;/FONT&gt;&lt;/B&gt; body&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; std&lt;B&gt;&lt;FONT COLOR="#663300"&gt;::&lt;/FONT&gt;&lt;/B&gt;string&lt;B&gt;&lt;FONT COLOR="#663300"&gt;(),&lt;/FONT&gt;&lt;/B&gt;&lt;FONT COLOR="#990000"&gt;
    const&lt;/FONT&gt;&lt;FONT COLOR="#FF6633"&gt; char&lt;/FONT&gt;&lt;B&gt;&lt;FONT COLOR="#663300"&gt; *&lt;/FONT&gt;&lt;/B&gt;verb&lt;B&gt;&lt;FONT COLOR="#663300"&gt; =&lt;/FONT&gt;&lt;/B&gt; NULL&lt;B&gt;&lt;FONT COLOR="#663300"&gt;);
};&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So the &lt;tt&gt;Scheduler&lt;/tt&gt; owns the (unseen to the library user)
connection &lt;tt&gt;Task&lt;/tt&gt; objects, and the connection &lt;tt&gt;Task&lt;/tt&gt;
objects own the &lt;tt&gt;Connection&lt;/tt&gt; stream target
objects. &lt;tt&gt;Connect()&lt;/tt&gt; can return immediate errors from the
socket &lt;tt&gt;::connect&lt;/tt&gt; call or from URL parsing, while deferring
any other errors to come back through a later &lt;tt&gt;OnDone&lt;/tt&gt; callback
&amp;mdash; all without there being any ambiguity of the lifetime of the
streams or their observers.&lt;/p&gt;

&lt;p&gt;(There would be a problem if the &lt;tt&gt;Connection&lt;/tt&gt; object also
had a smart pointer to the &lt;tt&gt;Task&lt;/tt&gt; object, as then neither would
ever be deleted and both would become &lt;a
href="http://en.wikipedia.org/wiki/Memory_leak#Reference_counting_and_cyclic_references"&gt;memory
leaks&lt;/a&gt;. But, because the data is pushed from the &lt;tt&gt;Task&lt;/tt&gt; to
the &lt;tt&gt;Connection&lt;/tt&gt;, the &lt;tt&gt;Connection&lt;/tt&gt; never needs to see
the &lt;tt&gt;Task&lt;/tt&gt; object &amp;mdash; and indeed can&amp;rsquo;t, because &lt;tt&gt;Task&lt;/tt&gt;s live and
die entirely inside library code, and users of the library can&amp;rsquo;t even
obtain pointers to them.)&lt;/p&gt;

&lt;table align=center&gt;&lt;tr&gt;&lt;td bgcolor=#eeeeee&gt;
&lt;table border=0&gt;
&lt;tr&gt;&lt;td align=left&gt;&lt;b&gt;Simplicity does not precede complexity, but follows it&lt;/b&gt;&lt;/td&gt;&lt;tr&gt;
&lt;tr&gt;&lt;td align=right&gt;&amp;mdash;&lt;i&gt;attributed to Alan Perlis&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So here&amp;rsquo;s the thing. The third design is clearly better than
the second. Well, it&amp;rsquo;s clearly better than the first, too, but
mainly because the first doesn&amp;rsquo;t work, which is a boring and
trivial way for one design to be better than another. The interesting
thing is that it&amp;rsquo;s better than the second.&lt;/p&gt;

&lt;p&gt;And better it certainly is &amp;mdash; making this change halved the
size of the code that uses the library, as well as making it more
intentional and less fragile and stylised.&lt;/p&gt;

&lt;p&gt;So why, having got to the second design, was I not satisfied? Why
did I carry on thinking about it, waiting for the inspiration of the
third design to strike? And why, having come up with the third design,
was there a feeling of happiness that wasn&amp;rsquo;t present when
writing the the second one, even when it passed all the unit tests the
first one failed?&lt;/p&gt;

&lt;p&gt;The only answer I can come up with is to theorise the existence of
an almost aesthetic sense of code quality &amp;mdash; which is worrying in
a couple of ways. Firstly, because what is instinctive is rarely
communicable, and what is not communicable is soon lost: a software
engineer&amp;rsquo;s fate is that of the wheelwright in the &lt;a
href="http://www.chinapage.com/story/wheelwright.html"&gt;old story of
Duke Huan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But worse than that: if code quality is in fact an aesthetic, and
thus extrarational, experience, then it raises the prospect that
others, even other good software engineers, could have a different
sense of aesthetics, ultimately resulting in a point where you and
they are pulling the same code in opposite directions. (I heard
recently of a software organisation, believers in the
currently-fashionable &amp;ldquo;agile&amp;rdquo;,
&amp;ldquo;refactor-mercilessly&amp;rdquo; style of development, in which two
otherwise talented engineers spent all their time rewriting each
others&amp;rsquo; code rather than pushing things forward &amp;mdash; as their
aesthetic senses, and frankly their assumptions about who was
&amp;ldquo;in charge&amp;rdquo; in the deliberately un-micro-managed
environment, butted heads.)&lt;/p&gt;

&lt;p&gt;No aesthete could get away with &amp;ldquo;correcting&amp;rdquo; the second
design above into the first: the failing unit tests would prevent
that. But are there those who would correct the third design into the
second, in the opposite direction to me? If so, why? And, even more
importantly, if &lt;em&gt;not&lt;/em&gt;, why not?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4645403140173980051?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4645403140173980051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/11/this-code-is-completely-bogus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4645403140173980051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4645403140173980051'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/11/this-code-is-completely-bogus.html' title='This Code Is Completely Bogus'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-6888342667719453625</id><published>2009-10-14T20:24:00.002+01:00</published><updated>2009-10-16T19:27:04.131+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Productivity Gains With KDE4</title><content type='html'>&lt;p&gt;Honesty&amp;rsquo;s a good thing, usually. In particular, it&amp;rsquo;s
usually a good thing in software engineering, in which most of what we
do is digital and repeatable, is either one thing or the other; this
fosters a culture of honesty in the same way that it does (or should
do) in science, as &lt;a
href="http://www.amazon.co.uk/Surely-Youre-Joking-Mr-Feynman-Adventures/dp/009917331X"&gt;Feynman&lt;/a&gt;
points out in &lt;a
href="http://www.lhup.edu/~dsimanek/cargocul.htm"&gt;&lt;i&gt;Cargo Cult
Science&lt;/i&gt;&lt;/a&gt;. Unlike in a courtroom, or even in a courtroom drama,
software engineering rarely comes down to one person&amp;rsquo;s word
against another. (Well, unless your co-workers are &lt;a
href="http://thedailywtf.com/Articles/Classic-WTF-Symbolic-Installation.aspx"&gt;sociopaths&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
But there are situations where more honesty isn&amp;rsquo;t a Good
Thing. One example, in fact, &lt;em&gt;is&lt;/em&gt; a courtroom drama: if
you&amp;rsquo;re writing such a thing, the principle of pure honesty would
have you title it something like &amp;ldquo;Not Guilty of Murder&amp;rdquo; &amp;mdash;
whereas, in fact, letting people know the verdict before they&amp;rsquo;ve
seen the piece robs it of its whole point.
&lt;/p&gt;

&lt;p&gt;
Now &lt;a href="http://en.wikipedia.org/wiki/KDE_3"&gt;&lt;sc&gt;KDE&lt;/sc&gt;3&lt;/a&gt; came with a
desktop toy called KPat, a patience game which (among others) includes
an implementation of the same &amp;ldquo;Klondike&amp;rdquo; patience found in
Windows Solitaire. The &lt;sc&gt;KDE&lt;/sc&gt;3 (3.5.10) version of KPat had a feature
where, if it detected you&amp;rsquo;d got into a situation where it was
impossible to complete the hand, it would stop the game and tell you
so. Naturally, such a feature has to be extremely conservative: it
must stop the game only when it can be proved that forward progress is
impossible. And in fact the algorithm in &lt;sc&gt;KDE&lt;/sc&gt;3 KPat was very
conservative indeed: it kicked-in so rarely that seeing the message
always came as a surprise, even on games you already knew you&amp;rsquo;d
lost.
&lt;/p&gt;

&lt;p&gt;
Occasionally I&amp;rsquo;d idly wonder whether the lost-game detection
could be improved &amp;mdash; but then I realised that actually, if you
improved it enough, you&amp;rsquo;d eventually get to a situation where
the game detects, and tells you, the moment you&amp;rsquo;ve made a move
that leads only to dead-ends. &amp;ldquo;OK, you&amp;rsquo;re an idiot, bye,
next.&amp;rdquo; There&amp;rsquo;d be no point playing the game at all.
&lt;/p&gt;

&lt;p&gt;
And yet, in the &lt;sc&gt;KDE&lt;/sc&gt;4 (4.3.2) version of KPat, that&amp;rsquo;s exactly
what&amp;rsquo;s been implemented. In the status bar, the whole time, is
one of two messages &amp;mdash; either &amp;ldquo;Solver: This game is
winnable&amp;rdquo; or &amp;ldquo;Solver: This game is not winnable in its
current state&amp;rdquo;. Any time you make a move that makes the first
message change to the second, you soon reconsider!
&lt;/p&gt;

&lt;p&gt;
And so, alongside the huge amount of work on the graphics (the
original neat bitmaps have become huge and flouncy SVG images; the
codebase diff is huge even ignoring the Solver; the whole thing has
unexpectedly acquired an Ancient Egyptian feel) the developers have
&lt;em&gt;completely ruined&lt;/em&gt; the actual game. All the time you&amp;rsquo;re
playing, it&amp;rsquo;s as if a stern examiner is watching over your
shoulder, always ready to lean forwards and intone &amp;ldquo;Now I
don&amp;rsquo;t believe you wanted to do that&amp;rdquo;. Worse, unlike the &lt;sc&gt;KDE&lt;/sc&gt;3
algorithm, which just summarised information you could already see,
the examiner
&lt;em&gt;can see the cards that you can&amp;rsquo;t&lt;/em&gt;, making it an eerily omniscient
guide, not to mention a shocking cheat.
&lt;/p&gt;

&lt;p&gt;
Solving patience is a great technical achievement. And it&amp;rsquo;s
certainly scrupulously &lt;em&gt;honest&lt;/em&gt; to tell the player exactly what
the prospects of success are. But it&amp;rsquo;s a technical achievement
that shouldn&amp;rsquo;t have been achieved (or shouldn&amp;rsquo;t be present
in the game itself, even though it can be turned off), and a case
where honesty is definitely not the best policy. And one of the best
little time-wasters in &lt;sc&gt;KDE&lt;/sc&gt; has, effectively, been eliminated.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-6888342667719453625?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/6888342667719453625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/10/productivity-gains-with-kde4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6888342667719453625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6888342667719453625'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/10/productivity-gains-with-kde4.html' title='Productivity Gains With KDE4'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4186215100450066969</id><published>2009-09-12T17:48:00.010+01:00</published><updated>2009-09-12T18:46:07.178+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='configury'/><title type='text'>Recursive Make Is A Time-Waster</title><content type='html'>&lt;p&gt;Now you&amp;rsquo;ve arranged to &lt;a
href="http://pdh11.blogspot.com/2009/09/four-quarters-of-codebase.html"&gt;divide
your project into libraries&lt;/a&gt;, how do you go about compiling them?&lt;/p&gt;

&lt;p&gt;Clearly you want to be able to do the whole thing in one go: to do
otherwise would be to fail the &lt;a
href="http://www.joelonsoftware.com/articles/fog0000000043.html"&gt;Joel
test&lt;/a&gt;. And you want all the dependencies to be checked every time:
there&amp;rsquo;s no bug harder to find than one that no longer actually exists
in the source you&amp;rsquo;re looking at. (And stale objects, not updated
following a header change, can lead to &lt;a
href="http://en.wikipedia.org/wiki/One_Definition_Rule"&gt;ODR
violations&lt;/a&gt;: in other words, to random spookiness and borkage that
the compiler and linker aren&amp;rsquo;t required to warn you about, and in many
cases can&amp;rsquo;t even theoretically do so.)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Automake"&gt;GNU Automake&lt;/a&gt; is
one answer to the problem, and makefiles in the same spirit as the
ones it generates are popular even in projects that don&amp;rsquo;t use
Automake. Such makefiles express inter-module dependencies, such as
that of an application on a library, by recursively invoking
&lt;tt&gt;make&lt;/tt&gt; in the library directory before invoking it again in the
application directory.&lt;/p&gt;

&lt;p&gt;For a variety of reasons, documented once and for all in the famous
paper &lt;a href="http://miller.emu.id.au/pmiller/books/rmch/"&gt;Recursive
&lt;tt&gt;make&lt;/tt&gt; Considered Harmful&lt;/a&gt;, this is a bad idea. The paper
suggests that for some systems, it&amp;rsquo;s even a bad idea for correctness
reasons &amp;mdash; that incorrect builds with inadequately-followed
dependencies can result. But the example given is that of a system
whose module dependencies can&amp;rsquo;t be serialised; this naturally means
Automake&amp;rsquo;s sequential run over the sub-Makefiles can&amp;rsquo;t do the Right
Thing. However, if the module dependencies can&amp;rsquo;t be serialised, that
means there&amp;rsquo;s a cycle and they don&amp;rsquo;t form a true hierarchy; that&amp;rsquo;s a
bad situation for more reasons than just Automake&amp;rsquo;s &amp;mdash; bad for
reusability, bad for unit-testability, and bad because it reveals that
the system designers haven&amp;rsquo;t really thought through what the
r&amp;ocirc;les of the modules are.&lt;/p&gt;

&lt;p&gt;So if that doesn&amp;rsquo;t apply to you, if your modules are properly
factored into a neat hierarchy, does that mean there&amp;rsquo;s less incentive
to ditch a recursive-&lt;tt&gt;make&lt;/tt&gt; scheme and take the time to write a
&lt;a
href="http://www.xs4all.nl/~evbergen/nonrecursive-make.html"&gt;non-recursive
one&lt;/a&gt;? Less, perhaps, but decidedly not &lt;em&gt;none&lt;/em&gt; &amp;mdash; because
there are substantial &lt;em&gt;performance&lt;/em&gt; benefits from whole-project
makefiles on modern systems.&lt;/p&gt;

&lt;p&gt;This effect is, to be fair, mentioned in &lt;em&gt;Recursive
&lt;tt&gt;make&lt;/tt&gt; Considered Harmful&lt;/em&gt; (7.1), but the author didn&amp;rsquo;t
draw it out on pretty graphs, nor quantify the improvements, so there
is scope for it to be better-documented.&lt;/p&gt;

&lt;p&gt;Suppose your project has ten components (nine libraries and the
application, say), each with between four and twenty source
files. These source files won&amp;rsquo;t, naturally, all take exactly the same
length of time to compile &amp;mdash; in fact, typically there&amp;rsquo;ll be quite a
wide range of compilation times, especially if only certain files
include certain rather profligate library headers. And further suppose
that the machine you&amp;rsquo;re compiling on has eight CPU cores or threads
(such machines are desktop-class these days), so you use
&lt;tt&gt;make&amp;nbsp;-j8&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;If your makefiles are like Automake&amp;rsquo;s, what happens is that
&lt;tt&gt;make&lt;/tt&gt; will make the first library using up to eight CPUs,
then, once that&amp;rsquo;s done, make the second library using up to eight
CPUs, and so on until it&amp;rsquo;s done all of them in the serialised order
you used in the top-level Makefile. Which is &lt;em&gt;correct&lt;/em&gt;, but
it&amp;rsquo;s not &lt;em&gt;efficient&lt;/em&gt;, because &lt;tt&gt;make&lt;/tt&gt; needlessly
serialises the &lt;em&gt;entire&lt;/em&gt; of each library build against the
&lt;em&gt;entire&lt;/em&gt; of the next one, when typically a library&amp;rsquo;s components
will each depend on only &lt;em&gt;some&lt;/em&gt; of the previous one&amp;rsquo;s targets.&lt;/p&gt;

&lt;p&gt;In graphical form, your CPU utilisation would look like the
following diagram, where time runs from left to right, each horizontal
row represents a different CPU, and blocks of the same colour belong
to the same library; the top half of the diagram shows CPU utilisation
during a recursive-&lt;tt&gt;make&lt;/tt&gt;-driven recompilation, and the bottom
half the same recompilation done with a whole-project Makefile.&lt;/p&gt;

&lt;p align=center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QXt0fgMWRn8/SqvVR8BI0aI/AAAAAAAAAA8/CMF17FExsaM/s1600-h/makej8.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 530px; height: 376px;" src="http://1.bp.blogspot.com/_QXt0fgMWRn8/SqvVR8BI0aI/AAAAAAAAAA8/CMF17FExsaM/s800/makej8.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5380628683969581474" /&gt;&lt;/a&gt;&lt;br&gt;
click for full-size&lt;/p&gt;

&lt;p&gt;Using one Makefile has allowed &lt;tt&gt;make&amp;nbsp;-j8&lt;/tt&gt; to keep all
eight CPUs busy the whole time &amp;mdash; as, whenever a CPU comes free, any
pending work from anywhere else in the project can be scheduled on
it. By contrast, the top half of the diagram has lots of whitespace,
where all the CPUs must wait each time until the last one &lt;em&gt;in that
library&lt;/em&gt; has finished.&lt;/p&gt;

&lt;p&gt;In this example, the build takes scarcely 70% of the time a
recursive build would do. If you have more cores, perhaps in a
multi-machine build farm, the benefit goes up: building on four cores
sees a reeduction only to 88%, but 12 cores sees the whole-project
build take just 59% as long as the recursive version, and on 16 cores
the time is better than halved. If, in the limit, you work for
Dr.&amp;nbsp;Evil, your entire company is basically one big compute
surface and you can use
&amp;ldquo;&lt;tt&gt;make&amp;nbsp;-j&amp;nbsp;one-meelion&lt;/tt&gt;&amp;rdquo;, then the
improvement factor is essentially the same as the number of libraries
&amp;mdash; in this case, 10x, though in practice if you went down that
route you&amp;rsquo;d find communication overheads starting to bite into
your scalability.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4186215100450066969?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4186215100450066969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/09/recursive-make-is-time-waster.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4186215100450066969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4186215100450066969'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/09/recursive-make-is-time-waster.html' title='Recursive Make Is A Time-Waster'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_QXt0fgMWRn8/SqvVR8BI0aI/AAAAAAAAAA8/CMF17FExsaM/s72-c/makej8.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4908602375205270248</id><published>2009-09-12T16:56:00.006+01:00</published><updated>2009-09-12T17:04:49.125+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Four Quarters Of The Codebase</title><content type='html'>&lt;p&gt;As a software project grows, eventually it becomes unwieldy to keep
the entire source in one single gigantic folder: you&amp;rsquo;ll need to
split it up. Canonically, and indeed quite correctly, the first idea
most architects then have is to split the source into a main program
plus one or more libraries that provide ancillary services.&lt;/p&gt;

&lt;p&gt;Once that&amp;rsquo;s done, everyone on the project who sits down to
write some new code, will have to think at least for a moment about
where to put the source file. The answer, of course, is that the new
code should go in the main program if it&amp;rsquo;s fairly specific to
the current project (or if it depends on code that&amp;rsquo;s already in
there), and into the library otherwise. The &amp;ldquo;force of
gravity&amp;rdquo; &amp;mdash; developers&amp;rsquo; sense of where code should go
unless there&amp;rsquo;s good reason otherwise &amp;mdash; should be in the
direction of pulling functionality over into the generic code.&lt;/p&gt;

&lt;p&gt;Sometimes this decision seems harder than it should be: if
that&amp;rsquo;s the case, what&amp;rsquo;s often going on is that the
functionality in question should really be split up &amp;mdash; with a
generic part in the library, and the specific use this project makes
of it in the main program. In this way, source code organisation can
act as a &lt;a
href="http://en.wikipedia.org/wiki/Behavior-shaping_constraint"&gt;forcing
function&lt;/a&gt; for good design.&lt;/p&gt;

&lt;p&gt;If that&amp;rsquo;s so useful, can we get &lt;em&gt;extra&lt;/em&gt; design-forcing
out of how we organise the source? One issue that often throws a
spanner in the works of software designs whose creators didn&amp;rsquo;t
originally bear it in mind, is portability between software
platforms. It would be decidedly helpful if the source code
organisation, and/or the system architecture it (one hopes) reflects,
could help prevent platform specialists from unthinkingly tying code
to a particular platform when in fact it&amp;rsquo;ll be needed more
widely in future.&lt;/p&gt;

&lt;p&gt;So instead of just application versus library, it&amp;rsquo;s helpful
to organise the codebase so that a developer sitting down to write new
code, will have to choose between &lt;em&gt;four&lt;/em&gt; different places to
put it:&lt;/p&gt;

&lt;br&gt;
  &lt;table align=center border cellpadding=10&gt;
  &lt;tr&gt;&lt;td&gt;Application-specific,&lt;br&gt;platform-specific&lt;/td&gt;
   &lt;td&gt;Library code,&lt;br&gt;platform-specific&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Application-specific,&lt;br&gt;platform-agnostic&lt;/td&gt;
   &lt;td&gt;Library code,&lt;br&gt;platform-agnostic&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;br&gt;

&lt;p&gt;This means that, if you&amp;rsquo;re writing an application that
you&amp;rsquo;re targetting at, say, both Iphone and Windows, or both
desktop and embedded, then the actual application logic needs to go in
the south-west corner, where implementations on any platform can use
it; user-interface code mostly goes in the north-east, where other
applications wanting similar UI components can use it; and only the
minimum of code necessary to wire the two together goes in the
north-west.&lt;/p&gt;

&lt;p&gt;The force of gravity in this diagram acts towards the south and the
east: if you can turn code from a Win32 application into generic Win32
components, or into a portable implementation of the logic,
that&amp;rsquo;s a design improvement. If you can split the code up, even
split a single class up, along those lines, that&amp;rsquo;s an
improvement too. And by forcing developers to make the four-way choice
before they write a source file, you&amp;rsquo;re helping everyone in the
team to think about these issues and to factor the code in the best
way as it&amp;rsquo;s first written. Fostering a feeling of &amp;ldquo;design
guilt&amp;rdquo;, in yourself or others, when placing functionality
further north or west than it belongs, gives everyone an
easily-grasped metric for well-factored designs.&lt;/p&gt;

&lt;p&gt;Really this just another way of thinking about &lt;a
href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;the
model-view-controller pattern&lt;/a&gt;; the mapping is straightforward,
except that MVC doesn&amp;rsquo;t have a word for the fourth quarter,
libraries which are assumed to be at a lower level than the components
MVC deals with:&lt;/p&gt;

  &lt;table align=center border cellpadding=5&gt;
  &lt;tr&gt;&lt;td&gt;Controllers&lt;/td&gt;
   &lt;td&gt;Views&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td&gt;Models&lt;/td&gt;
   &lt;td&gt;&lt;i&gt;(Libraries)&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;
&lt;br&gt;

&lt;p&gt;but, even so, embodying MVC in the source layout itself means that its
issues get thought about earlier in the software process.&lt;/p&gt;

&lt;p&gt;Now naturally, any real codebase above a certain size won&amp;rsquo;t
consist of just &amp;ldquo;the&amp;rdquo; application and &amp;ldquo;the&amp;rdquo;
library. There&amp;rsquo;ll be a whole collection of libraries, and
perhaps of applications too, arranged in a dependency graph &amp;mdash;
hopefully, for reasons &lt;a
href="http://www.amazon.co.uk/Large-Scale-C-Software-Design-APC/dp/0201633620"&gt;Lakos&lt;/a&gt;
expounds, a graph which forms a non-cyclic &lt;a
href="http://chorale.sourceforge.net/doc/"&gt;hierarchy&lt;/a&gt;. But it
should be possible to partition this graph into (up to) four parts,
matching the four quarters of the codebase, and &lt;em&gt;with all
dependency arrows pointing southwards, eastwards, or
south-eastwards&lt;/em&gt;. No view or model should depend on a controller;
no platform-agnostic library should depend on any view, model or
controller. Again, these are truisms of MVC design, but thinking about
them in their four quarters gives an easy visual way of thinking about
and discussing the issues.&lt;/p&gt;

&lt;p align=center&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QXt0fgMWRn8/SqvGByXD6DI/AAAAAAAAAAs/jBEJSrNVM-8/s1600-h/12a.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 362px; height: 242px;" src="http://4.bp.blogspot.com/_QXt0fgMWRn8/SqvGByXD6DI/AAAAAAAAAAs/jBEJSrNVM-8/s400/12a.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5380611913824856114" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Incidentally, my own &lt;a href="http://chorale.sf.net"&gt;Chorale&lt;/a&gt;
codebase currently (as of v0.15) fails this test, or at least gets a
technical pass only: it doesn&amp;rsquo;t have any &lt;em&gt;platform-specific
library&lt;/em&gt; code or directories, as all that code is rather bogusly
stuffed in the &lt;em&gt;application-specific, platform-specific&lt;/em&gt;
directories. (Some classes are, in fact, platform-specific library
classes, but the split isn&amp;rsquo;t enforced in the source
organisation, either by libraries or by directories.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4908602375205270248?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4908602375205270248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/09/four-quarters-of-codebase.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4908602375205270248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4908602375205270248'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/09/four-quarters-of-codebase.html' title='Four Quarters Of The Codebase'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QXt0fgMWRn8/SqvGByXD6DI/AAAAAAAAAAs/jBEJSrNVM-8/s72-c/12a.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-6319793980157031308</id><published>2009-07-16T20:19:00.000+01:00</published><updated>2009-07-16T20:20:36.293+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Little Libraries</title><content type='html'>&lt;p&gt;How small can you make a library?&lt;/p&gt;

&lt;p&gt;Of course, one way to make it smaller is to make each individual
file smaller: by using an optimising compiler, by turning off
exceptions, by removing debug information (in release builds). But
even once you&amp;rsquo;ve done that, there&amp;rsquo;s extra overhead involved in just
being a library: how can &lt;em&gt;that&lt;/em&gt; be minimised?&lt;/p&gt;

&lt;p&gt;One choice that affects the answer, is whether you want a shared or
a static library. Sometimes other considerations force the answer, but
if you have the luxury of being able to choose either type, which do
you choose for best compactness?&lt;/p&gt;

&lt;p&gt;Both types have their advantages; static libraries are useful when
the client, or most clients, use only a fraction of the library
facilities: unused objects from the archive simply aren&amp;rsquo;t linked. By
contrast, client code that uses any one facility from a shared library
must link all of it. And the position-independent code (PIC)
techniques needed to build a shared library, may be more expensive
than normal code on some architectures. On the other hand, shared
libraries offer control over symbol visibility, so an
internally-complex library with a simple interface, can end up simple
rather than complex at link-time. And, because a shared library is
all-or-nothing anyway, it can be built as a single translation unit
with no loss of generality &amp;mdash; enabling better compiler
optimisation.&lt;/p&gt;

&lt;p&gt;So I tried it. I took &lt;tt&gt;libupnpd&lt;/tt&gt; from Chorale, which is a
small-to-medium sized library although with very few entry points, and
tried to make it as small as possible while retaining its identity as
a separate library. Here are the sizes it came out as, in the various attempts, as reported by size(1):&lt;/p&gt;

&lt;style type="text/css"&gt;&lt;!--
 td + td { text-align: right }

 dd { margin: 5pt 0pt 5pt 36pt }

// --&gt;
&lt;/style&gt;

&lt;table&gt;
&lt;col&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;&lt;col align=right&gt;
&lt;tr&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;td rowspan=12 bgcolor=#cccccc&gt;&lt;/td&gt;&lt;th colspan=6&gt;amd64-linux&lt;/th&gt;&lt;td rowspan=12 bgcolor=#cccccc&gt;&lt;/td&gt;&lt;th colspan=6&gt;arm-linux&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;text&lt;/th&gt;&lt;th&gt;data&lt;/th&gt;&lt;th&gt;bss&lt;/th&gt;&lt;th&gt;total&lt;/th&gt;&lt;th colspan=2&gt;relative&lt;/th&gt;&lt;th&gt;text&lt;/th&gt;&lt;th&gt;data&lt;/th&gt;&lt;th&gt;bss&lt;/th&gt;&lt;th&gt;total&lt;/th&gt;&lt;th colspan=2&gt;relative&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Static library                 &lt;/td&gt;&lt;td&gt;161443&lt;/td&gt;&lt;td&gt;   8&lt;/td&gt;&lt;td&gt; 94&lt;/td&gt;&lt;td&gt;161545&lt;/td&gt;&lt;td&gt;                  0.0%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-23.9%&lt;/td&gt;&lt;td&gt;140176&lt;/td&gt;&lt;td&gt;   4&lt;/td&gt;&lt;td&gt;872&lt;/td&gt;&lt;td&gt;141052&lt;/td&gt;&lt;td&gt;  0.0%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-24.1%&lt;/td&gt;&lt;/tr&gt;
&lt;tr bgcolor=#eeffff&gt;&lt;td&gt;Shared library                 &lt;/td&gt;&lt;td&gt;205846&lt;/td&gt;&lt;td&gt;6216&lt;/td&gt;&lt;td&gt;112&lt;/td&gt;&lt;td&gt;212174&lt;/td&gt;&lt;td bgcolor=#ffcccc&gt;+31.3%&lt;/td&gt;&lt;td&gt;                  0.0%&lt;/td&gt;&lt;td&gt;177469&lt;/td&gt;&lt;td&gt;7968&lt;/td&gt;&lt;td&gt;412&lt;/td&gt;&lt;td&gt;185849&lt;/td&gt;&lt;td bgcolor=#ffcccc&gt;+31.8%&lt;/td&gt;&lt;td&gt;  0.0%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Shared library, sec          &lt;/td&gt;&lt;td&gt;205844&lt;/td&gt;&lt;td&gt;6216&lt;/td&gt;&lt;td&gt; 80&lt;/td&gt;&lt;td&gt;212140&lt;/td&gt;&lt;td bgcolor=#ffcccc&gt;+31.3%&lt;/td&gt;&lt;td&gt;                  0.0%&lt;/td&gt;&lt;td&gt;177421&lt;/td&gt;&lt;td&gt;7960&lt;/td&gt;&lt;td&gt;248&lt;/td&gt;&lt;td&gt;185629&lt;/td&gt;&lt;td bgcolor=#ffcccc&gt;+31.6%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;- 0.1%&lt;/td&gt;&lt;/tr&gt;
&lt;tr bgcolor=#eeffff&gt;&lt;td&gt;Shared library, vis            &lt;/td&gt;&lt;td&gt;144726&lt;/td&gt;&lt;td&gt;5328&lt;/td&gt;&lt;td&gt;112&lt;/td&gt;&lt;td&gt;150166&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;- 7.0%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-29.2%&lt;/td&gt;&lt;td&gt;120012&lt;/td&gt;&lt;td&gt;7472&lt;/td&gt;&lt;td&gt;412&lt;/td&gt;&lt;td&gt;127896&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;- 9.3%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-31.2%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Shared library, sec vis      &lt;/td&gt;&lt;td&gt;144078&lt;/td&gt;&lt;td&gt;5328&lt;/td&gt;&lt;td&gt; 80&lt;/td&gt;&lt;td&gt;149486&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;- 7.5%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-29.5%&lt;/td&gt;&lt;td&gt;119452&lt;/td&gt;&lt;td&gt;7472&lt;/td&gt;&lt;td&gt;248&lt;/td&gt;&lt;td&gt;127172&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;- 9.8%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-31.6%&lt;/td&gt;&lt;/tr&gt;
&lt;tr bgcolor=#eeffff&gt;&lt;td&gt;Shared library, whole sec vis&lt;/td&gt;&lt;td&gt;133582&lt;/td&gt;&lt;td&gt;5312&lt;/td&gt;&lt;td&gt; 80&lt;/td&gt;&lt;td&gt;138974&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-14.0%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-34.5%&lt;/td&gt;&lt;td&gt;107623&lt;/td&gt;&lt;td&gt;7468&lt;/td&gt;&lt;td&gt;412&lt;/td&gt;&lt;td&gt;115503&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-18.1%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-37.9%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Single object, whole           &lt;/td&gt;&lt;td&gt;101011&lt;/td&gt;&lt;td&gt;3112&lt;/td&gt;&lt;td&gt; 94&lt;/td&gt;&lt;td&gt;104217&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-35.5%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-50.9%&lt;/td&gt;&lt;td&gt; 85112&lt;/td&gt;&lt;td&gt;6688&lt;/td&gt;&lt;td&gt;380&lt;/td&gt;&lt;td&gt; 92180&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-34.6%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-50.4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr bgcolor=#eeffff&gt;&lt;td&gt;Single object, whole sec     &lt;/td&gt;&lt;td&gt;100638&lt;/td&gt;&lt;td&gt;3112&lt;/td&gt;&lt;td&gt; 94&lt;/td&gt;&lt;td&gt;103844&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-35.7%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-51.1%&lt;/td&gt;&lt;td&gt; 85112&lt;/td&gt;&lt;td&gt;6688&lt;/td&gt;&lt;td&gt;380&lt;/td&gt;&lt;td&gt; 92180&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-34.6%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-50.4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Single object, whole sec vis &lt;/td&gt;&lt;td&gt; 99775&lt;/td&gt;&lt;td&gt;3112&lt;/td&gt;&lt;td&gt; 94&lt;/td&gt;&lt;td&gt;102981&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-36.2%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-51.5%&lt;/td&gt;&lt;td&gt; 85120&lt;/td&gt;&lt;td&gt;6688&lt;/td&gt;&lt;td&gt;380&lt;/td&gt;&lt;td&gt; 92188&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-34.6%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-50.4%&lt;/td&gt;&lt;/tr&gt;
&lt;tr bgcolor=#eeffff&gt;&lt;td&gt;Single object, whole sec vis wp&lt;/td&gt;&lt;td&gt; 99287&lt;/td&gt;&lt;td&gt;3112&lt;/td&gt;&lt;td&gt; 94&lt;/td&gt;&lt;td&gt;102493&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-36.6%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-51.7%&lt;/td&gt;&lt;td&gt; 85028&lt;/td&gt;&lt;td&gt;6688&lt;/td&gt;&lt;td&gt;380&lt;/td&gt;&lt;td&gt; 92096&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-34.7%&lt;/td&gt;&lt;td bgcolor=#ccffcc&gt;-50.5%&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;br&gt;

&lt;p&gt;Some explanation is, of course, in order.&lt;/p&gt;

&lt;dl&gt;
 &lt;dt&gt;1. Static library&lt;/dt&gt;

 &lt;dd&gt;Each file compiled separately, archived with &lt;tt&gt;ar&lt;/tt&gt;.&lt;/dd&gt;

 &lt;dt&gt;2. Shared library&lt;/dt&gt; 

      &lt;dd&gt;Standard ELF shared library: each file compiled separately
      with &lt;tt&gt;-fPIC&lt;/tt&gt;, linked with &lt;tt&gt;gcc -shared&lt;/tt&gt;. (Or, in fact,
      using libtool for simplicity. But that&amp;rsquo;s what libtool was
      doing behind the scenes.) &lt;/dd&gt;
 
&lt;dt&gt;3. Shared library, sec&lt;/dt&gt;

 &lt;dd&gt;As (2), but compiled also with &lt;tt&gt;-ffunction-sections
 -fdata-sections&lt;/tt&gt;, and linked with &lt;tt&gt;--gc-sections&lt;/tt&gt;. This made
 approximately one gnat&amp;rsquo;s crotchet of difference.&lt;/dd&gt;

&lt;dt&gt;4. Shared library, vis&lt;/dt&gt;

      &lt;dd&gt;As (2), but compiled also with &lt;tt&gt;-fvisibility=hidden
      -fvisibility-inlines-hidden&lt;/tt&gt;, and with the small number of
      entry points labelled
      &lt;tt&gt;__attribute__((visibility("default")))&lt;/tt&gt;.  This should
      indeed have been much better than (2) or (3), but it came as a
      surprise to me that it&amp;rsquo;s also better than (1).&lt;/dd&gt;

&lt;dt&gt;5. Shared library, sec vis&lt;/dt&gt;

     &lt;dd&gt;As (2) but with both the (3) and (4) optimisations
     applied. Again, &lt;tt&gt;--gc-sections&lt;/tt&gt; makes a non-zero but
     insignificant difference.&lt;/dd&gt;

&lt;dt&gt;6. Shared library, whole sec vis&lt;/dt&gt;

     &lt;dd&gt;&lt;p&gt;OK, now we&amp;rsquo;re getting somewhere. This is as (5), but
     with the whole library built as a single translation
     unit. It&amp;rsquo;s the moral equivalent of GCC&amp;rsquo;s
     &lt;tt&gt;-combine&lt;/tt&gt;, but as that only applies to C and this is C++,
     it&amp;rsquo;s done by writing a small &lt;tt&gt;.cpp&lt;/tt&gt; file that does
     nothing but &lt;tt&gt;#include&lt;/tt&gt; all the other &lt;tt&gt;.cpp&lt;/tt&gt;
     files. (Doing this requires a certain discipline in the files in
     question, so as not to queer the pitch for subsequent code. But
     it&amp;rsquo;s certainly not an intolerable imposition.)&lt;/p&gt;

 &lt;p&gt;In the interests of scrupulous accuracy, I should point out
 that in fact not the &lt;em&gt;whole&lt;/em&gt; of the library is compiled
 in the one file. One of the component parts needs special
 compiler options, so that one&amp;rsquo;s still compiled
 separately.&lt;/p&gt;

      &lt;p&gt;These settings correspond to what you get if you configure
 and build KDE3 with &lt;tt&gt;--enable-final&lt;/tt&gt;.&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;7. Single object, whole&lt;/dt&gt;

   &lt;dd&gt;This is like the non-shared-library version of (6); the whole
   library is compiled in a single translation unit, but this time
   into an ordinary, non-PIC, object file, which is then put in a library
   by itself.&lt;/dd&gt;

&lt;dt&gt;8. Single object, whole sec&lt;/dt&gt;

   &lt;dd&gt;As (7), but in little sections as per (3). This doesn&amp;rsquo;t
   make much difference on amd64-linux, and none at all on
   arm-linux.&lt;/dd&gt;

&lt;dt&gt;9. Single object, whole sec vis&lt;/dt&gt;

   &lt;dd&gt;As (8) but with the visibility settings too. As those settings
   are only meant to apply to shared libraries, this shouldn&amp;rsquo;t
   have made a difference. But for some reason, it did, albeit a tiny
   one.&lt;/dd&gt;

&lt;dt&gt;10. Single object, whole sec vis wp&lt;/dt&gt;

   &lt;dd&gt;&lt;p&gt;As (9) but with the single library translation unit compiled
   with &lt;tt&gt;-fwhole-program&lt;/tt&gt;, and the exported functions labelled
   &lt;tt&gt;__attribute__((externally_visible))&lt;/tt&gt;.&lt;/p&gt;

 &lt;p&gt;Semantically and philosophically, this is saying much the
 same thing as the visibility settings.  But there must be some
 extra little bit of optimisation the compiler can do in this
 situation. There isn&amp;rsquo;t a corresponding statistic for a
 &lt;em&gt;shared&lt;/em&gt; library with &lt;tt&gt;-fwhole-program&lt;/tt&gt;, as
 using that option disables PIC.&lt;/p&gt;&lt;/dd&gt;

&lt;/dl&gt;

The effects of these various optimisations are remarkably similar, in
relative terms, across both architectures.

&lt;h3&gt;Why size(1) Isn&amp;rsquo;t The Full Story&lt;/h3&gt;

&lt;p&gt;Especially considering the library is C++, some of the numbers
above need to be taken with a slight pinch of salt. Most C++ programs
have a lot of functions declared in header files; functions which are
semantically &lt;tt&gt;inline&lt;/tt&gt; but which, for various reasons (such as
being listed in a vtable) aren&amp;rsquo;t actually purely inlined in
practice. Such functions are emitted in every object file, in
&amp;ldquo;link-once&amp;rdquo; sections, which are deduplicated by the final
linker and emitted only once each.&lt;/p&gt;

&lt;p&gt;The size(1) command counts these link-once sections under
&amp;ldquo;text&amp;rdquo;, and doesn&amp;rsquo;t do any deduplication. So a
static library made of many object files will often have a larger size
(as quoted by size(1)) than it will actually add to the final binary
&amp;mdash; because of the multiple copies of all the link-once
sections. So row (1) of the table is somewhat inflated &amp;mdash; and in
fact the &amp;ldquo;single object&amp;rdquo; rows are very slightly inflated,
too, as although they only contain one each of the
&amp;ldquo;link-once&amp;rdquo; sections, those will still get deduplicated
again against any that are also used elsewhere in the final binary. In
shared libraries, on the other hand, link-once sections are
deduplicated when the shared library itself is linked, but can&amp;rsquo;t
be deduplicated again at dynamic link time. So those numbers really do
represent the amount that gets added to the final application
footprint.&lt;/p&gt;

&lt;p&gt;Interestingly (and fortunately, seeing as libupnpd
&lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; actually the whole program), using
-fwhole-program still emits the link-once sections, so they do get
deduplicated against the final binary.&lt;/p&gt;

&lt;h3&gt;Why, If You Really Want Small, You Should Ignore All This&lt;/h3&gt;

&lt;p&gt;As the massive leap in density between the shared-library and
single-object numbers in the graph show, the compiler can do a
&lt;em&gt;lot&lt;/em&gt; better the more of your program it sees at once. So for
the very smallest binaries, take this principle and turn it up to
eleven: abandon (for release builds) the idea of using separate
libraries at all, and compile your &lt;em&gt;entire program and all its
&amp;ldquo;library&amp;rdquo; code&lt;/em&gt; as a &lt;em&gt;single&lt;/em&gt; translation
unit.&lt;/p&gt;

&lt;p&gt;Not that that&amp;rsquo;s a good idea if the library code itself is
part of the product: if you don&amp;rsquo;t install the library, no other
clients can link against it, and if you install the library but your
program doesn&amp;rsquo;t use it, that&amp;rsquo;s wasted RAM when other
processes load the library copies of all that code. But for
&amp;ldquo;libraries&amp;rdquo; tightly wedded to a single binary, and
especially for embedded systems (where typically there &lt;em&gt;are&lt;/em&gt; no
other processes), it does get you better code size than even the best
options above.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-6319793980157031308?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/6319793980157031308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/07/little-libraries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6319793980157031308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6319793980157031308'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/07/little-libraries.html' title='Little Libraries'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-4687563517449623266</id><published>2009-06-17T15:32:00.004+01:00</published><updated>2009-06-17T19:51:15.852+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='configury'/><title type='text'>Type Erasure, boost::mutex, And The617</title><content type='html'>&lt;p&gt;The &lt;a
href="http://www.boost.org/doc/libs/1_39_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_types"&gt;&lt;tt&gt;boost::mutex&lt;/tt&gt;&lt;/a&gt;
class is certainly &lt;i&gt;not&lt;/i&gt; considered harmful. It&amp;rsquo;s jolly good,
especially the way it, and its companion &lt;tt&gt;boost::condition&lt;/tt&gt;,
work properly on Win32. But it doesn&amp;rsquo;t half include a lot of header
files to obtain all that jolly goodness.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s get GCC to tell us what header files it includes. To do this,
we need GCC&amp;rsquo;s dependency generation features, the ones normally used
for generating Makefile fragments listing all the files a translation
unit depends on.

&lt;blockquote&gt;&lt;pre&gt;$ echo "#include &amp;lt;boost/thread/mutex.hpp&amp;gt;" \
      | g++ -xc++ -E - -MP -M | grep ^/usr | sort
&lt;b&gt;&lt;i&gt;...long list...&lt;/i&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

OK, that&amp;rsquo;s indeed quite a lot of headers. How many exactly? (using GCC 4.3.3,
amd64-linux, Boost 1.39.0)

&lt;blockquote&gt;&lt;pre&gt;$ echo "#include &amp;lt;boost/thread/mutex.hpp&amp;gt;" \
      | g++ -xc++ -E - -MP -M | grep ^/usr | sort | wc -l
&lt;b&gt;618&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

Yes, a source file that includes nothing but
&lt;tt&gt;&amp;lt;boost/thread/mutex.hpp&amp;gt;&lt;/tt&gt; has actually also read &lt;i&gt;six
hundred and seventeen&lt;/i&gt; other headers by the time it&amp;rsquo;s done.&lt;/p&gt;

&lt;p&gt;Now I&amp;rsquo;d hate to be one of those bloggers who does nothing but sit
around and &lt;a href="http://xkcd.com/386/"&gt;grouse&lt;/a&gt; about the people
who are actually doing useful work. But I humbly submit that having to
include 618 C++ headers just to get hold of a mutex class, is, in an
objective sense, rather a lot.
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QXt0fgMWRn8/Sjk7BOIXHQI/AAAAAAAAAAc/By8chSLJ6fo/s1600-h/9b.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 337px; height: 172px;" src="http://3.bp.blogspot.com/_QXt0fgMWRn8/Sjk7BOIXHQI/AAAAAAAAAAc/By8chSLJ6fo/s400/9b.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5348370924638248194" align=right /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QXt0fgMWRn8/Sjj-0M8N6oI/AAAAAAAAAAM/59g0fthU3S8/s1600-h/9a.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 198px; height: 172px;" src="http://4.bp.blogspot.com/_QXt0fgMWRn8/Sjj-0M8N6oI/AAAAAAAAAAM/59g0fthU3S8/s320/9a.gif" border="0" align=left alt=""id="BLOGGER_PHOTO_ID_5348304730282912386" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Really what&amp;rsquo;s wanted is one of the &amp;ldquo;complete
insulation&amp;rdquo; or type-erasure techniques from &lt;a
href="http://www.amazon.co.uk/Large-Scale-C-Software-Design-APC/dp/0201633620"&gt;Lakos&lt;/a&gt;
section 6.4, so that instead of the situation on the left &amp;mdash; where
every file in the project which needs a mutex, includes the Boost
header and its 617 dependencies &amp;mdash; we get the situation on the right,
where only the encapsulating file needs to know the details, and
everyone else can just include the simple leaf header
&lt;tt&gt;my_mutex.h&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;The problem is, every encapsulation technique discussed by Lakos
has an inevitable cost in efficiency. Whichever way you slice it &amp;mdash;
whether you use a mutex protocol class plus a factory, or whether you
use the handle/body or pimpl pattern &amp;mdash; you tend to end up needing to
call &lt;tt&gt;new&lt;/tt&gt; and &lt;tt&gt;delete&lt;/tt&gt;, not just every time you create
or destroy a mutex, but every time you create or destroy a mutex
scoped-lock object. Especially for rarely-contended locks, that
overhead can easily swamp the actual implementation time.&lt;/p&gt;

&lt;p&gt;The issue is, that to end up with a &lt;tt&gt;boost::mutex&lt;/tt&gt;, client
code must either construct one itself &amp;mdash; depending on
&lt;tt&gt;boost::mutex&lt;/tt&gt; &amp;ldquo;in size&amp;rdquo; is Lakos&amp;rsquo;s term &amp;mdash;
or call other code which hands one back, which latter scheme
necessarily requires an allocation.&lt;/p&gt;

&lt;p&gt;So how can we solve this impasse? How can we depend on
&lt;tt&gt;boost::mutex&lt;/tt&gt; &amp;ldquo;in size&amp;rdquo;, without depending on all its
headers?&lt;/p&gt;

&lt;p&gt;Well, we can cheat. We can populate &lt;tt&gt;my_mutex.h&lt;/tt&gt; with
classes whose objects are the same size as &lt;tt&gt;boost::mutex&lt;/tt&gt;es
&amp;mdash; and which, within the file &lt;tt&gt;my_mutex.cpp&lt;/tt&gt;, &lt;i&gt;are&lt;/i&gt;
&lt;tt&gt;boost::mutex&lt;/tt&gt;es &amp;mdash; but whose actual type is invisible to
other clients of &lt;tt&gt;my_mutex.h&lt;/tt&gt;. The idea is to behave a bit like
this:

&lt;!--

class Mutex
{
    char m_data[sizeof(boost::mutex)];

public:
    Mutex()
    {
        new(m_data) boost::mutex;
    }
    ~Mutex()
    {
        ((boost::mutex*)m_data)-&gt;~mutex();
    }
};

--&gt;

&lt;blockquote&gt;&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;&lt;pre&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; Mutex&lt;b&gt;&lt;font color="#663300"&gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
    char&lt;/font&gt; m_data&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;sizeof&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;)];&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
    {&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
        new&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;;
    }
    ~&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
    {
        ((&lt;/font&gt;&lt;/b&gt;boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;*)&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)-&amp;gt;~&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;();
    }
};&lt;/font&gt;&lt;/b&gt;&lt;/pre&gt;&lt;/blockquote&gt;

though of course that doesn&amp;rsquo;t yet help as-is, as you still need to
include the 617 to get &lt;tt&gt;sizeof(boost::mutex)&lt;/tt&gt; to compile.&lt;/p&gt;

&lt;p&gt;To eliminate the dependencies, you need to know
&lt;tt&gt;sizeof(boost::mutex)&lt;/tt&gt; ahead of time. Probably the best way to do this,
is to get your configury to work it out, by adding lines like these to
your &lt;tt&gt;configure.ac&lt;/tt&gt;:
&lt;blockquote&gt;&lt;tt&gt;AC_LANG_PUSH([C++])&lt;br&gt;
AC_CHECK_SIZEOF([boost::mutex],, [[#include&amp;nbsp;&amp;lt;boost/thread/mutex.hpp&amp;gt;]])&lt;br&gt;
AC_CHECK_SIZEOF([boost::condition],, [[#include&amp;nbsp;&amp;lt;boost/thread/condition.hpp&amp;gt;]])&lt;br&gt;
AC_CHECK_SIZEOF([boost::mutex::scoped_lock],, [[#include&amp;nbsp;&amp;lt;boost/thread/mutex.hpp&amp;gt;]])&lt;br&gt;
AC_LANG_POP
&lt;/tt&gt;&lt;/blockquote&gt;

which will leave you with lines like this in your &lt;tt&gt;config.h&lt;/tt&gt;:

&lt;blockquote&gt;&lt;tt&gt;
#define SIZEOF_BOOST__CONDITION 88&lt;br&gt;
#define SIZEOF_BOOST__MUTEX 40&lt;br&gt;
#define SIZEOF_BOOST__MUTEX__SCOPED_LOCK 16&lt;br&gt;
&lt;/tt&gt;&lt;/blockquote&gt;

giving you exactly what you need to write &lt;tt&gt;my_mutex.h&lt;/tt&gt;. (One day when
you want to see something deliciously evil, go and look at the way
Autoconf determines such size information when cross-compiling,
without depending on any particular compiler or linker.) The result
looks like this:

&lt;!--
/* my_mutex.h */
#include "config.h"

class Mutex
{
    char m_data[SIZEOF_BOOST__MUTEX];

public:
    Mutex();
    ~Mutex();
};


/* my_mutex.cpp */
#include "my_mutex.h"
#include &lt;boost/thread/mutex.hpp&gt;

Mutex::Mutex()
{
    new(m_data) boost::mutex;
}

Mutex::~Mutex()
{
    ((boost::mutex*)m_data)-&gt;~mutex();
}

--&gt;

&lt;blockquote&gt;&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;&lt;pre&gt;&lt;i&gt;&lt;font color="#999999"&gt;/* my_mutex.h */&lt;/font&gt;&lt;/i&gt;&lt;font color="#000099"&gt;
#include "config.h"
&lt;/font&gt;&lt;font color="#990000"&gt;
class&lt;/font&gt; Mutex&lt;b&gt;&lt;font color="#663300"&gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
    char&lt;/font&gt; m_data&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;SIZEOF_BOOST__MUTEX&lt;b&gt;&lt;font color="#663300"&gt;];&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    Mutex&lt;b&gt;&lt;font color="#663300"&gt;();
    ~&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;();
};&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;


/* my_mutex.cpp */&lt;/font&gt;&lt;/i&gt;&lt;font color="#000099"&gt;
#include "my_mutex.h"
#include &amp;lt;boost/thread/mutex.hpp&amp;gt;
&lt;/font&gt;
Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    new&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;;
}&lt;/font&gt;&lt;/b&gt;

Mutex&lt;b&gt;&lt;font color="#663300"&gt;::~&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
{
    ((&lt;/font&gt;&lt;/b&gt;boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;*)&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)-&amp;gt;~&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;();
}&lt;/font&gt;&lt;/b&gt;&lt;/pre&gt;&lt;/blockquote&gt;

which is indeed good enough to free client code from the burden of the
617.&lt;/p&gt;

&lt;p&gt;But if you&amp;rsquo;re doing this wrapping for more than one class &amp;mdash;
Chorale wanted at least &lt;tt&gt;boost::mutex&lt;/tt&gt;,
&lt;tt&gt;boost::mutex::scoped_lock&lt;/tt&gt;, and &lt;tt&gt;boost::condition&lt;/tt&gt; &amp;mdash;
you start to realise you&amp;rsquo;re writing the same thing many times over,
and that it really ought to be wrapped up in a template. (An attempt
is also made to avoid alignment issues, a worry which might already
have been nagging at you after the above snippets; an assertion
checks that the configury got the right answer for the size.) Here it is:

&lt;blockquote&gt;&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;&lt;pre&gt;&lt;font color="#990000"&gt;template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; T&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
struct&lt;/font&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

/** Wrap up a type so that even clients who depend on it in size,
 * don't have to see its declaration.
 */&lt;/font&gt;&lt;/i&gt;&lt;font color="#990000"&gt;
template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; T&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt; unsigned int&lt;/font&gt; sz&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
class&lt;/font&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    union&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
        char&lt;/font&gt; m_data&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;sz&lt;b&gt;&lt;font color="#663300"&gt;];&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
        void&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;m_align&lt;b&gt;&lt;font color="#663300"&gt;;
    };&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

    /** Use a nested class, rather than using WrappedType&amp;lt;T&amp;gt;::type
     * directly, so that we can be sure that its destructor is called
     * "~Wrapped" -- if T1 is a typedef-name, its destructor won't be
     * called "~T1".
     */&lt;/font&gt;&lt;/i&gt;&lt;font color="#990000"&gt;
    class&lt;/font&gt; Wrapped&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; public&lt;/font&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;T&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;::&lt;/font&gt;&lt;/b&gt;type&lt;b&gt;&lt;font color="#663300"&gt;
    {&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
        Wrapped&lt;b&gt;&lt;font color="#663300"&gt;() {}&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

        template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; Arg&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
        explicit&lt;/font&gt; Wrapped&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Arg&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; arg&lt;b&gt;&lt;font color="#663300"&gt;) :&lt;/font&gt;&lt;/b&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;T&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;::&lt;/font&gt;&lt;/b&gt;type&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;arg&lt;b&gt;&lt;font color="#663300"&gt;) {}
    };&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    Wrapper&lt;b&gt;&lt;font color="#663300"&gt;()
    {&lt;/font&gt;&lt;/b&gt;
        BOOST_STATIC_ASSERT&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;sizeof&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Wrapped&lt;b&gt;&lt;font color="#663300"&gt;) ==&lt;/font&gt;&lt;/b&gt; sz&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
        new&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt; Wrapped&lt;b&gt;&lt;font color="#663300"&gt;;
    }&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

    template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; Arg&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    explicit&lt;/font&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Arg&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; arg&lt;b&gt;&lt;font color="#663300"&gt;)
    {&lt;/font&gt;&lt;/b&gt;
        BOOST_STATIC_ASSERT&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;sizeof&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Wrapped&lt;b&gt;&lt;font color="#663300"&gt;) ==&lt;/font&gt;&lt;/b&gt; sz&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
        new&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt; Wrapped&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;arg&lt;b&gt;&lt;font color="#663300"&gt;);
    }

    ~&lt;/font&gt;&lt;/b&gt;Wrapper&lt;b&gt;&lt;font color="#663300"&gt;()
    {
        ((&lt;/font&gt;&lt;/b&gt;Wrapped&lt;b&gt;&lt;font color="#663300"&gt;*)&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;)-&amp;gt;~&lt;/font&gt;&lt;/b&gt;Wrapped&lt;b&gt;&lt;font color="#663300"&gt;();
    }&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

    /** Calls to Unwrap() will only compile following a definition of
     * WrappedType&amp;lt;T&amp;gt; -- not in client code.
     */&lt;/font&gt;&lt;/i&gt;
    Wrapped&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; Unwrap&lt;b&gt;&lt;font color="#663300"&gt;() {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *(&lt;/font&gt;&lt;/b&gt;Wrapped&lt;b&gt;&lt;font color="#663300"&gt;*)&lt;/font&gt;&lt;/b&gt;m_data&lt;b&gt;&lt;font color="#663300"&gt;; }
};&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

Armed with this, &lt;tt&gt;my_mutex.h&lt;/tt&gt; can be very straightforward:

&lt;blockquote&gt;&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;&lt;pre&gt;&lt;font color="#000099"&gt;#include "config.h"
#include "wrapper.h"
&lt;/font&gt;&lt;i&gt;&lt;font color="#999999"&gt;
/** Wrap a boost::mutex so we don't include so very many headers.
 */&lt;/font&gt;&lt;/i&gt;&lt;font color="#990000"&gt;
class&lt;/font&gt; Mutex&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; public&lt;/font&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; SIZEOF_BOOST__MUTEX&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    Mutex&lt;b&gt;&lt;font color="#663300"&gt;();
    ~&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;();&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

    class&lt;/font&gt; Lock&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; public&lt;/font&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; SIZEOF_BOOST__MUTEX__SCOPED_LOCK&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
    {&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
        Lock&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;);
        ~&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;();
    };
};&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

class&lt;/font&gt; Condition&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; public&lt;/font&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Condition&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; SIZEOF_BOOST__CONDITION&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    Condition&lt;b&gt;&lt;font color="#663300"&gt;();
    ~&lt;/font&gt;&lt;/b&gt;Condition&lt;b&gt;&lt;font color="#663300"&gt;();&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

    bool&lt;/font&gt; Wait&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt; unsigned int&lt;/font&gt; sec&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

    void&lt;/font&gt; NotifyOne&lt;b&gt;&lt;font color="#663300"&gt;();&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
    void&lt;/font&gt; NotifyAll&lt;b&gt;&lt;font color="#663300"&gt;();
};&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

and &lt;tt&gt;my_mutex.cpp&lt;/tt&gt; not much less straightforward; note that
&lt;tt&gt;WrappedType&amp;lt;T&amp;gt;&lt;/tt&gt; is used like a traits class, in that the
intended wrapped type is &amp;ldquo;revealed&amp;rdquo; by specialising
&lt;tt&gt;WrappedType&lt;/tt&gt; for the particular wrapper type &amp;mdash; it&amp;rsquo;s only
following such a specialisation, that the constructor, destructor, or
&lt;tt&gt;Unwrap()&lt;/tt&gt; calls will compile:

&lt;blockquote&gt;&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;&lt;pre&gt;&lt;font color="#000099"&gt;#include "my_mutex.h"
#include &amp;lt;boost/thread/mutex.hpp&amp;gt;
#include &amp;lt;boost/thread/condition.hpp&amp;gt;
&lt;/font&gt;&lt;font color="#990000"&gt;
template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
struct&lt;/font&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    typedef&lt;/font&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex type&lt;b&gt;&lt;font color="#663300"&gt;;
};&lt;/font&gt;&lt;/b&gt;

Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
{
}&lt;/font&gt;&lt;/b&gt;

Mutex&lt;b&gt;&lt;font color="#663300"&gt;::~&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;()
{
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
struct&lt;/font&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    typedef&lt;/font&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;scoped_lock type&lt;b&gt;&lt;font color="#663300"&gt;;
};&lt;/font&gt;&lt;/b&gt;

Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; mutex&lt;b&gt;&lt;font color="#663300"&gt;)
    :&lt;/font&gt;&lt;/b&gt; Wrapper&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;SIZEOF_BOOST__MUTEX__SCOPED_LOCK&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;(&lt;/font&gt;&lt;/b&gt;mutex&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;Unwrap&lt;b&gt;&lt;font color="#663300"&gt;())
{
}&lt;/font&gt;&lt;/b&gt;

Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;::~&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;()
{
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
struct&lt;/font&gt; WrappedType&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&lt;/font&gt;&lt;/b&gt;Condition&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    typedef&lt;/font&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;condition type&lt;b&gt;&lt;font color="#663300"&gt;;
};&lt;/font&gt;&lt;/b&gt;

Condition&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Condition&lt;b&gt;&lt;font color="#663300"&gt;()
{
}&lt;/font&gt;&lt;/b&gt;

Condition&lt;b&gt;&lt;font color="#663300"&gt;::~&lt;/font&gt;&lt;/b&gt;Condition&lt;b&gt;&lt;font color="#663300"&gt;()
{
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

bool&lt;/font&gt; Condition&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Wait&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;Mutex&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;Lock&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; lock&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt; unsigned int&lt;/font&gt; sec&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    return&lt;/font&gt; Unwrap&lt;b&gt;&lt;font color="#663300"&gt;().&lt;/font&gt;&lt;/b&gt;timed_wait&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;lock&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;Unwrap&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; boost&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;posix_time&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;seconds&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;sec&lt;b&gt;&lt;font color="#663300"&gt;));
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

void&lt;/font&gt; Condition&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;NotifyAll&lt;b&gt;&lt;font color="#663300"&gt;()
{&lt;/font&gt;&lt;/b&gt;
    Unwrap&lt;b&gt;&lt;font color="#663300"&gt;().&lt;/font&gt;&lt;/b&gt;notify_all&lt;b&gt;&lt;font color="#663300"&gt;();
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

void&lt;/font&gt; Condition&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;NotifyOne&lt;b&gt;&lt;font color="#663300"&gt;()
{&lt;/font&gt;&lt;/b&gt;
    Unwrap&lt;b&gt;&lt;font color="#663300"&gt;().&lt;/font&gt;&lt;/b&gt;notify_one&lt;b&gt;&lt;font color="#663300"&gt;();
}&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;/p&gt;

&lt;p&gt;So this technique is neat if a bit icky (with the casting and the
explicit size-checking). Is it worthwhile? For Chorale, the answer was
certainly &amp;ldquo;yes&amp;rdquo;. Chorale is vigorously multi-threaded, and
many parts of the system use mutexes. Using a script a bit like the
GCC-based dependency counter from the very top of this post, it turns
out that Chorale&amp;rsquo;s 250ish source files and 250ish headers, had
between them nearly 240,000 dependencies. Wrapping up just
&lt;tt&gt;boost::mutex&lt;/tt&gt; and &lt;tt&gt;boost::condition&lt;/tt&gt; reduced that
number to 115,000 &amp;mdash; meaning that &lt;i&gt;more than half of all header
files&lt;/i&gt; compiled while compile the whole of Chorale, a fairly large
and complex program, get compiled &lt;i&gt;solely&lt;/i&gt; to satisfy the
dependencies of &lt;tt&gt;boost::mutex&lt;/tt&gt;. This startling figure is also
borne out by the total time taken to compile (with a cold pagecache):

&lt;table align=center&gt;&lt;tr&gt;&lt;th&gt;Before wrapping&lt;th&gt;&lt;th&gt;After wrapping&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre&gt;real    4m0.304s
user    10m33.296s
sys     1m38.870s&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;     &lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre&gt;real    2m39.516s
user    6m10.523s
sys     1m9.452s&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

...a 42% improvement. It is just possible that there&amp;rsquo;s a run-time
efficiency impact of this wrapping, as the mutex operations now all
get inlined into &lt;tt&gt;my_mutex.cpp&lt;/tt&gt; and not directly into the client
code. However, as is the way with these things, it&amp;rsquo;s really just as
likely that this gives a performance improvement &amp;mdash; some of these
Boost calls inline a &lt;i&gt;lot&lt;/i&gt; of code, especially under Win32.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-4687563517449623266?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/4687563517449623266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/06/type-erasure-boostmutex-and-the617.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4687563517449623266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/4687563517449623266'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/06/type-erasure-boostmutex-and-the617.html' title='Type Erasure, boost::mutex, And The617'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QXt0fgMWRn8/Sjk7BOIXHQI/AAAAAAAAAAc/By8chSLJ6fo/s72-c/9b.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-2622579367361767998</id><published>2009-05-30T23:44:00.001+01:00</published><updated>2009-05-30T23:44:56.252+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>How Not To Develop On Windows</title><content type='html'>&lt;p&gt;This is a HOW-TO on writing Windows software, including GUI
software, without using a Windows box at all except for final
testing. Among other benefits, this lets you develop in the simple,
testable, scriptable Linux environment; it means you don&amp;rsquo;t have
to forever check things in and out of source-control to test whether
you&amp;rsquo;ve broken the other platform&amp;rsquo;s builds; and it&amp;rsquo;s
also handy if you&amp;rsquo;ve got a powerful Linux box but only a feeble
Windows box.&lt;/p&gt;

&lt;p&gt;Well, actually, it isn&amp;rsquo;t really a HOW-TO, in the grand
tradition; it&amp;rsquo;s more of a &amp;ldquo;WHETHER-TO&amp;rdquo;. That&amp;rsquo;s
because it doesn&amp;rsquo;t always go into enough detail to let you
reconstruct everything described, but it at least tells you that
it&amp;rsquo;s possible &amp;mdash; so that if you&amp;rsquo;re wondering
&lt;i&gt;whether-to&lt;/i&gt; try and develop Windows software in this fashion,
you can be reassured, before setting off in that direction, that the
destination is attainable.&lt;/p&gt;

&lt;p&gt;There are a lot of bits and pieces to set up a complete
cross-development and cross-test environment. We should all be hugely
grateful for the vast amount of development effort put in by the GCC,
binutils, Mingw, Wine, Qt and other projects to enable the setup
described in this one small blog post.&lt;/p&gt;

&lt;h3&gt;1. A cross-compiler toolchain targetting Mingw32&lt;/h3&gt;

&lt;p&gt;&lt;tt&gt;apt-get install mingw32-binutils mingw32-runtime mingw32&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, configure and install GNU binutils for target
&amp;ldquo;&lt;tt&gt;i586-mingw32&lt;/tt&gt;&amp;rdquo;; install the headers from the &lt;a
href="http://sourceforge.net/project/showfiles.php?group_id=2435"&gt;mingw32-runtime&lt;/a&gt;
package (which you can&amp;rsquo;t build yet); configure and install a
Stage 1 cross-GCC with

&lt;blockquote&gt;&lt;tt&gt;--target=i586-mingw32 --enable-languages="c"
--enable-threads=win32 --disable-libmudflap --disable-libssp
--enable-__cxa_atexit --enable-sjlj-exceptions
--disable-win32-registry --with-gnu-as --with-gnu-ld
&lt;/tt&gt;&lt;/blockquote&gt;

as extra configure arguments; configure and install the &lt;a
href="http://sourceforge.net/project/showfiles.php?group_id=2435"&gt;w32api&lt;/a&gt;
package; configure and install the mingw32-runtime package; and
finally configure and install a Stage 2 fully-working cross-GCC with

&lt;blockquote&gt;&lt;tt&gt;--target=i586-mingw32 --enable-languages="c,c++"
--enable-threads=win32 --disable-libmudflap --disable-libssp
--enable-__cxa_atexit --enable-sjlj-exceptions
--disable-win32-registry --with-gnu-as --with-gnu-ld
--disable-libstdcxx-pch
--enable-libstdcxx-allocator=new&lt;/tt&gt;&lt;/blockquote&gt;

as configure arguments. Note that, supposing you want everything to
live in &lt;tt&gt;/usr/local/i586-mingw32&lt;/tt&gt;, you need to give GCC and
binutils &amp;ldquo;&lt;tt&gt;--prefix=/usr/local&lt;/tt&gt;&amp;rdquo;, and everything
else &amp;ldquo;&lt;tt&gt;--prefix=/usr/local/i586-mingw32&lt;/tt&gt;&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Except for using w32api and mingw-runtime instead of glibc, this
isn&amp;rsquo;t that different from how to build a cross-compiler for any
other target.&lt;/p&gt;

&lt;p&gt;If you want to use the exact same versions of everything I did,
it&amp;rsquo;s binutils&amp;nbsp;2.19.51.0.2, mingw-runtime&amp;nbsp;3.14, w32api&amp;nbsp;3.11, and GCC&amp;nbsp;4.3.3.&lt;/p&gt;

&lt;p&gt;A recently-invented third alternative, which I haven&amp;rsquo;t tried,
is the &amp;ldquo;official&amp;rdquo; cross-hosted Mingw build tool scripts,
which are available on &lt;a
href="http://sourceforge.net/project/showfiles.php?group_id=2435"&gt;the
Mingw Sourceforge page&lt;/a&gt;.

&lt;h3&gt;2. A native pkgconfig for your cross-compiled libraries&lt;/h3&gt;

&lt;p&gt;Cross-compiled libraries for Mingw32 will put their pkgconfig
&amp;ldquo;&lt;tt&gt;.pc&lt;/tt&gt;&amp;rdquo; files in
&lt;tt&gt;/usr/local/i586-mingw32/lib/pkgconfig&lt;/tt&gt;. In order for configure
scripts targetting Mingw32 to find them, you&amp;rsquo;ll need a
&amp;ldquo;cross-pkgconfig&amp;rdquo; &amp;mdash; but one which, like a
cross-compiler, is built for the build platform, not the target
platform. If it&amp;rsquo;s named using the target prefix, as if it were
part of the cross-compiler &amp;mdash; i.e., in our case,
&lt;tt&gt;i586-mingw32-pkgconfig&lt;/tt&gt; &amp;mdash; configure scripts will use it
to determine which cross-compiled libraries are present.&lt;/p&gt;

&lt;p&gt;Configure &lt;a
href="http://pkg-config.freedesktop.org/"&gt;pkgconfig&lt;/a&gt; 0.23 with:

&lt;blockquote&gt;&lt;tt&gt;--with-pc-path=/usr/local/i586-mingw32/lib/pkgconfig --program-prefix=i586-mingw32-
&lt;/tt&gt;&lt;/blockquote&gt;

(yes, that ends with a hyphen).&lt;/p&gt;

&lt;h3&gt;3. Cross-compiled versions of all the libraries you use&lt;/h3&gt;

&lt;p&gt;How hard it is to arrange for these, depends a lot on each
individual library. In theory all you should need to do is configure
the library with &amp;ldquo;&lt;tt&gt;--prefix=/usr/local/i586-mingw32
--host=i586-mingw32&lt;/tt&gt;&amp;rdquo;, but in practice very few libraries do
the Right Thing with that alone. (Honourable mentions here go to
libxml2 and taglib.)&lt;/p&gt;

&lt;p&gt;Other things you might have to do to more recalcitrant libraries
include: setting &lt;tt&gt;CC=i586-mingw32-gcc&lt;/tt&gt; (and sometimes
&lt;tt&gt;CXX&lt;/tt&gt;, &lt;tt&gt;AR&lt;/tt&gt; and/or &lt;tt&gt;RANLIB&lt;/tt&gt; similarly); disabling
parts of the library (for libcdio use

&lt;blockquote&gt;&lt;tt&gt;--disable-joliet --disable-example-progs
--without-iso-info --without-iso-read --without-cd-info
--without-cd-drive --without-cd-read&lt;/tt&gt;&lt;/blockquote&gt;

to disable all the example programs) &amp;mdash; or, if the worst comes to
the worst, actually patching out bits of the library. I had to do that
to make taglib compile as a static library.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://boost.org"&gt;Boost&lt;/a&gt;, as usual, presents the most
challenging fight you&amp;rsquo;ll have with a build system. Here, without
further commentary, is the Makefile snippet needed to cross-compile
Boost for Mingw32; &lt;tt&gt;$(BUILD)&lt;/tt&gt; is the build directory and
&lt;tt&gt;$(PREFIX)&lt;/tt&gt; is where to install the result &amp;mdash;
&lt;tt&gt;/usr/local&lt;/tt&gt; would match a toolchain built as described above:

&lt;pre&gt;
cross-mingw32-boost:
        mkdir -p $(BUILD)/cross-mingw32-boost
        tar xjf boost-*bz2 -C $(BUILD)/cross-mingw32-boost
        cd $(BUILD)/cross-mingw32-boost/* \
                &amp;&amp; ./bootstrap.sh --prefix=$(PREFIX)/i586-mingw32 \
                        --libdir=$(PREFIX)/i586-mingw32/lib \
                        --includedir=$(PREFIX)/i586-mingw32/include \
                &amp;&amp; echo \
"using gcc : : i586-mingw32-g++ : &amp;lt;compileflags&amp;gt;-mthreads &amp;lt;linkflags&amp;gt;-mthreads ;" \
              &amp;gt; jtl-config.jam \
                &amp;&amp; ./bjam -q --layout=system variant=release \
                        link=static threading=multi --without-iostreams \
                        -sGXX=i586-mingw32-g++ --without-python \
                        threadapi=win32 --user-config=jtl-config.jam \
                &amp;&amp; sudo rm -rf $(PREFIX)/i586-mingw32/include/boost \
                &amp;&amp; sudo ./bjam -q --layout=system variant=release \
                        link=static threading=multi --without-iostreams \
                        -sGXX=i586-mingw32-g++ --without-python \
                        threadapi=win32 --user-config=jtl-config.jam install
        for i in $(PREFIX)/i586-mingw32/lib/libboost_*.a ; do \
   sudo i586-mingw32-ranlib $$i ; \
 done
        rm -rf $(BUILD)/cross-mingw32-boost
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Again, if you&amp;rsquo;d like a checklist of successes I&amp;rsquo;ve had
here, then with greater or lesser effort it&amp;rsquo;s proved possible to
make cross-compiled versions of zlib&amp;nbsp;1.2.3, Boost&amp;nbsp;1.39.0,
libcdio&amp;nbsp;0.80, taglib&amp;nbsp;1.5, and libxml2&amp;nbsp;2.6.30.

&lt;h3&gt;4. Wine Is Not an Emulator&lt;/h3&gt;

&lt;p&gt;Configure and install &lt;a href="http://winehq.com"&gt;Wine&lt;/a&gt;
1.0.1. Admirably, this just works out of the box, though if your Linux
box is 64-bit, you&amp;rsquo;ll need the 32-bit versions of its dependent
libraries installed.&lt;/p&gt;

&lt;p&gt;Having got this far, you should have all you need to compile, link,
and test Windows programs. Of course, they do have to be Windows
programs; Mingw is not Cygwin, and your program needs to be compatible
with real, proper Windows including &lt;tt&gt;&amp;lt;windows.h&amp;gt;&lt;/tt&gt;,
&lt;tt&gt;WSAEventSelect&lt;/tt&gt;, &lt;tt&gt;CreateWindowEx&lt;/tt&gt; and all that jazz
&amp;mdash; plus, of course, the Windows &lt;a
href="http://pdh11.blogspot.com/2009/05/unicode-is-one-true-god-and-utf-8-is.html"&gt;text-encoding&lt;/a&gt;
and &lt;a
href="http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html"&gt;file-naming&lt;/a&gt;
rules.&lt;/p&gt;

&lt;p&gt;Indeed, depending on how your project&amp;rsquo;s unit-tests are set
up, you can probably run most of them, too, under Wine. Just arrange
for them to be invoked using Wine: instead of
&amp;ldquo;&lt;tt&gt;run-test&amp;nbsp;various-args&lt;/tt&gt;&amp;rdquo;, execute instead
&amp;ldquo;&lt;tt&gt;wine&amp;nbsp;run-test&amp;nbsp;various-args&lt;/tt&gt;&amp;rdquo;. In some
situations, this alone would justify the effort of setting up a
cross-development environment: the ability to know, before checking in
code on Linux, that it passes all its tests &lt;em&gt;both&lt;/em&gt; on Linux and
Windows.&lt;/p&gt;

&lt;h3&gt;5. Qt&lt;/h3&gt;

&lt;p&gt;Trolltech&amp;rsquo;s, now Nokia&amp;rsquo;s, &lt;a
href="http://troll.no"&gt;Qt&lt;/a&gt; framework has for a while been a really
good way of writing open-source Linux GUI applications without getting
bogged down in X11 or other unhelpful toolkits. Originally Qt was only
available for free on the X11 platform, but subsequently the Windows
(and even MacOS) versions were also made available to the free
software community, and more recently still have been relicensed under
the GNU LGPL. This makes it not only a good way of writing open-source
Linux applications, but both open-source and proprietary applications
on Linux and Windows (and, again, MacOS too).&lt;/p&gt;

&lt;p&gt;So it would be handy if a cross-compiled version of Qt could be
used to write and test Windows versions of Linux Qt applications using
Wine. The problem is, Qt&amp;rsquo;s sources are &lt;i&gt;huge&lt;/i&gt; &amp;mdash; twice
the size of KOffice, three times the size of Firefox, five times the
size of GLib+GTK put together &amp;mdash; which is enough to put a fellow
off trying to cross-compile it.&lt;/p&gt;

&lt;p&gt;But fortunately, Trolltech supply a binary installer for the
Windows development libraries &amp;mdash; an installer &lt;em&gt;which works
under Wine&lt;/em&gt;. So, download
&lt;tt&gt;qt-win-opensource-&lt;/tt&gt;&lt;i&gt;x.y.z&lt;/i&gt;&lt;tt&gt;.exe&lt;/tt&gt; and run it under
Wine. Pick an installation directory (for instance,
&lt;tt&gt;/usr/local/i586-mingw32/qt&lt;/tt&gt; &amp;mdash; or, in Mingw-speak,
&lt;tt&gt;Z:\usr\local\i586-mingw32\qt&lt;/tt&gt;), and let it install. When it
asks for a Mingw installation, give it your cross-compiler&amp;rsquo;s
prefix directory (e.g. &lt;tt&gt;/usr/local/i586-mingw32&lt;/tt&gt;); it&amp;rsquo;ll
moan, but let you ignore the moaning and install anyway (do so).&lt;/p&gt;

&lt;p&gt;You then need to arrange for Qt&amp;rsquo;s pkgconfig files to be
available to the cross-compiler. The Win32 installation of Qt
doesn&amp;rsquo;t have pkgconfig files, but you can modify the ones from a
native Linux installation of the same version of Qt. To do this, issue
the following commands (as root):

&lt;blockquote&gt;&lt;pre&gt;# cd /usr/lib/pkgconfig     (Or wherever your existing QtCore.pc is)
# for i in Qt*.pc ; do sed \
   -e 's,^prefix=.*,prefix=/usr/local/i586-mingw32/qt,' \
   -e 's,-I.*/include,-I/usr/local/i586-mingw32/qt/include,' \
   -e 's,-l[^ ]*,&amp;4,' \
 &amp;lt; $i &amp;gt; /usr/local/i586-mingw32/lib/pkgconfig/$i ; done
&lt;/pre&gt;&lt;/blockquote&gt;

The three &lt;tt&gt;sed&lt;/tt&gt; replacements fix up the &lt;tt&gt;prefix=&lt;/tt&gt; lines
in the &lt;tt&gt;.pc&lt;/tt&gt; files, then fix up stray &lt;tt&gt;-I&lt;/tt&gt; directives in
the &lt;tt&gt;CFLAGS&lt;/tt&gt; lines that don&amp;rsquo;t use the defined
&lt;tt&gt;prefix&lt;/tt&gt;, then finally take account of the extra versioning
present in the Windows filenames (instead of &lt;tt&gt;QtCore.lib&lt;/tt&gt;,
Windows has &lt;tt&gt;QtCore4.lib&lt;/tt&gt;, and similarly across the whole
framework).&lt;/p&gt;

&lt;p&gt;(It was getting a development version of &lt;a
href="http://chorale.sf.net"&gt;Chorale&lt;/a&gt;&amp;rsquo;s Qt GUI more-or-less
up under Wine, and thus bringing Win32 into its sights for the first
time, that prompted the writing of this blog post.)&lt;/p&gt;

&lt;h3&gt;6. The Promised Land&lt;/h3&gt;

&lt;p&gt;So there you (hopefully, by now) have it. A well-behaved program,
such as Chorale, should mostly configure, build, unit-test, and run
its Windows version straightforwardly on a Linux box.&lt;/p&gt;

&lt;p&gt;Naturally, you still need to use a real Windows box for final
testing &amp;mdash; not everything that can happen on a real Windows box
can be modelled inside Wine, and nor is everything necessarily as
compatible between different Windows versions as you&amp;rsquo;d hope. But
by marginalising Windows out of its own development process until as
late as possible, the rest of the development can be eased, indeed
accelerated, by only having to develop on a single platform.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-2622579367361767998?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/2622579367361767998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/05/how-not-to-develop-on-windows.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/2622579367361767998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/2622579367361767998'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/05/how-not-to-develop-on-windows.html' title='How Not To Develop On Windows'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-7136550123655056089</id><published>2009-05-26T22:30:00.000+01:00</published><updated>2009-05-26T22:40:44.420+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>PathCanonicalize Versus What It Says On The Tin</title><content type='html'>&lt;blockquote&gt;&lt;i&gt;This post contains MathML mark-up, which may not
display correctly on some browsers. (And if you&amp;rsquo;re wondering how
to do &lt;a
href="http://computeraki.blogspot.com/2006/05/mathml-in-blogger.html"&gt;MathML
in Blogger&lt;/a&gt;, see &lt;a
href="http://www1.chapman.edu/~jipsen/mathml/mathhtml/"&gt;here&lt;/a&gt;.)
&lt;/i&gt;&lt;/blockquote&gt;

&lt;p&gt;Here&amp;rsquo;s what canonicalisation is. You&amp;rsquo;ve got a set of
items, and you can test those items for &lt;em&gt;equality&lt;/em&gt;,
&lt;nobr&gt;&lt;math&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/math&gt;&lt;/nobr&gt;, but what you
actually want to do is test for &lt;em&gt;equivalence&lt;/em&gt;,
&lt;nobr&gt;&lt;math&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;&amp;#x0224d;&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/math&gt;&lt;/nobr&gt;
&amp;mdash; where equality implies equivalence, but equivalence
doesn&amp;rsquo;t imply equality. What&amp;rsquo;s needed is a
canonicalisation function which maps the equivalence relation onto the
equality relation, by mapping all (of each subset of) equivalent items
onto a single representative item; a function &lt;math&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/math&gt;

such that

&lt;math display=block&gt;
&lt;mrow&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;&lt;mfenced&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mfenced&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;&lt;mfenced&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mfenced&gt;
 &lt;mspace width="1em"&gt;&lt;/mspace&gt;
 &lt;mo&gt;&amp;#x021d4;&lt;/mo&gt;
 &lt;mspace width="1em"&gt;&lt;/mspace&gt;
 &lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;&amp;#x0224D;&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;
&lt;/mrow&gt;
&lt;/math&gt;

(plus you want canonicalisation to be idempotent:
&lt;nobr&gt;&lt;math&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;
  &lt;mfenced&gt;
   &lt;mrow&gt;
    &lt;mi&gt;f&lt;/mi&gt;
    &lt;mfenced&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mfenced&gt;
   &lt;/mrow&gt;
  &lt;/mfenced&gt;
  &lt;mo&gt;&amp;#x02261;&lt;/mo&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;&lt;mfenced&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mfenced&gt;
&lt;/math&gt;&lt;/nobr&gt;
).


&lt;/p&gt;

&lt;p&gt;More concretely, suppose you&amp;rsquo;re keeping a database of disk
files, perhaps to enable searching or browsing. The question is, when
do two filenames refer to the same file? You can&amp;rsquo;t just test
them for string &lt;em&gt;equality&lt;/em&gt;, as two distinct names might refer
to the same file: on Unix, &lt;tt&gt;/home/peter/foo&lt;/tt&gt; and
&lt;tt&gt;/home/peter/src/../foo&lt;/tt&gt; are the same file. Plus, symbolic
links can be used to make even unrelated-looking names refer to the
same file. If your database lists the file by one name, and someone
does a query looking for another name, it won&amp;rsquo;t be found &amp;mdash;
and worse, the file could get into the database several times under
different names, perhaps with conflicting or stale information.&lt;/p&gt;

&lt;p&gt;But fortunately, &amp;ldquo;..&amp;rdquo;, &amp;ldquo;.&amp;rdquo;, and symlinks
between them are about the size of it for Unix ways of obscuring the
naming of a file, and the standard library comes with a suitable
canonicalisation function that will reduce elaborated forms into the
single unambiguous original pathname. (In fact, the GNU C library
comes with &lt;em&gt;two&lt;/em&gt; such functions, as the more-portable one,
&lt;tt&gt;realpath()&lt;/tt&gt;, needs a little care in use in order to avoid
buffer-overrun attacks; the GNU one,
&lt;tt&gt;canonicalize_file_name()&lt;/tt&gt;, does not.) So you canonicalise all
filenames as you store them into your database, and make sure to
canonicalise all filenames in queries before you look them up, and
you&amp;rsquo;ll get the right matches.&lt;/p&gt;

&lt;p&gt;And then eventually you&amp;rsquo;re going to want to port that
software to Windows &amp;mdash; whereupon you&amp;rsquo;ve got a problem.&lt;/p&gt;

&lt;p&gt;Indeed, you&amp;rsquo;ve got a whole little family of problems, because
even once you&amp;rsquo;ve navigated the treacherous waters of the &lt;a
href="http://pdh11.blogspot.com/2009/05/unicode-is-one-true-god-and-utf-8-is.html"&gt;textual
encoding&lt;/a&gt; of filenames under Win32, there still remain a
bewildering variety of ways to refer to the same file:

&lt;table align=center&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;D:\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Probably canonical&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;D:/Music/Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Slash versus backslash&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;D:\MUSIC\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Case-insensitive per locale&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;D:\Music\FOOLSG~1.FLA&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; MS-DOS 8.3&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;M:\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; After &amp;ldquo;subst M: D:\Music&amp;rdquo;&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\Device\HarddiskVolume2\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; If D: is local&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\server\share\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; If D: is a network drive&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\?\UNC\server\share\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Or like this&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\?\D:\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Ultra-long-filenames mode&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\.\D:\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Device namespace&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\?\UNC\D:\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Allegedly&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt&gt;\\?\Volume{&lt;i&gt;GUID&lt;/i&gt;}\Music\Fools Gold.flac&lt;/tt&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;&amp;mdash; Crikey&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;

&lt;p&gt;This whole dismal farrago really calls for a path canonicalisation
function. Which is why it&amp;rsquo;s unfortunate that there isn&amp;rsquo;t
one, and doubly unfortunate that there&amp;rsquo;s a function called
&lt;tt&gt;PathCanonicalize()&lt;/tt&gt; that &lt;em&gt;particularly&lt;/em&gt; isn&amp;rsquo;t
one, and not just because it&amp;rsquo;s spelled with a
&amp;ldquo;Z&amp;rdquo;. All that &lt;tt&gt;PathCanonicalize()&lt;/tt&gt; does is remove
&amp;ldquo;/../&amp;rdquo; and &amp;ldquo;/./&amp;rdquo; substrings &amp;mdash; it&amp;rsquo;s
a purely textual transformation and doesn&amp;rsquo;t even touch the
filesystem. It certainly doesn&amp;rsquo;t satisfy the
&amp;ldquo;canonicaliser condition&amp;rdquo;:&lt;/p&gt;

&lt;p align=center&gt;
&lt;math&gt;
&lt;mrow&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;&lt;mfenced&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mfenced&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt; &lt;/mo&gt;&lt;mfenced&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mfenced&gt;
 &lt;mspace width="1em"&gt;&lt;/mspace&gt;
 &lt;mo&gt;&amp;#x021d4;&lt;/mo&gt;
 &lt;mspace width="1em"&gt;&lt;/mspace&gt;
&lt;mi&gt;x&lt;/mi&gt;
&lt;/mrow&gt;
&lt;/math&gt;
and &lt;math&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/math&gt; are the same file&lt;/p&gt;

&lt;p&gt;No, there&amp;rsquo;s no shortcut for doing it laboriously and
textually (nor for having lots of unit tests to cover all those
ridiculous cases). The plan is, use &lt;tt&gt;GetFullPathName()&lt;/tt&gt; to turn
relative paths into absolute, then repeatedly call
&lt;tt&gt;QueryDosDevice()&lt;/tt&gt; to unwind subst&amp;rsquo;d drive letters, then
call &lt;tt&gt;GetLongPathName()&lt;/tt&gt; to get rid of 8.3-ness and
canonicalise case, and then finally, if &lt;tt&gt;GetDriveType()&lt;/tt&gt; says
it&amp;rsquo;s remote, use &lt;tt&gt;WNetGetUniversalName()&lt;/tt&gt; to convert the
remaining drive letter into a UNC path.&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;
std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;string Canonicalise&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;string&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; path&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt;
    std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring utf16&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; UTF8ToUTF16&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;path&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

    wchar_t&lt;/font&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;MAX_PATH&lt;b&gt;&lt;font color="#663300"&gt;];&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

    /** Note that PathCanonicalize does NOT do what we want here -- it's a
     * purely textual operation that eliminates /./ and /../ only.
     */&lt;/font&gt;&lt;/i&gt;
    DWORD rc&lt;b&gt;&lt;font color="#663300"&gt; = ::&lt;/font&gt;&lt;/b&gt;GetFullPathNameW&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; MAX_PATH&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; NULL&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;rc&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
        return&lt;/font&gt; path&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;

    utf16&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;

    if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;length&lt;b&gt;&lt;font color="#663300"&gt;() &amp;gt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 6&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)
    {&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;
        /** Get rid of \\?\ and \\.\ prefixes on drive-letter paths */&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;
        if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;wcsncmp&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L"\\\\?\\"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;) &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;5&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;
            utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;erase&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
        else if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;wcsncmp&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L"\\\\.\\"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;) &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;5&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;
            utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;erase&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);
    }&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;

    if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;length&lt;b&gt;&lt;font color="#663300"&gt;() &amp;gt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 10&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)
    {&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;
        /** Get rid of \\?\UNC on drive-letter and UNC paths */&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;
        if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;wcsncmp&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L"\\\\?\\UNC\\"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 8&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;))
        {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;9&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;10&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L'\\'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;
                utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;erase&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;8&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            else&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;
            {&lt;/font&gt;&lt;/b&gt;
                utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;erase&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;7&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;
                utf16&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L"\\"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; +&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;;
            }
        }
    }&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

    /** Anything other than UNC and drive-letter is something we don't
     * understand
     */&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;
    if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L'\\'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;1&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L'\\'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)
    {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
        if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '?'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; ||&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '.'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            return&lt;/font&gt; path&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt; // Not understood
&lt;/font&gt;&lt;/i&gt;&lt;i&gt;&lt;font color="#999999"&gt;
        /** OK -- UNC */&lt;/font&gt;&lt;/i&gt;&lt;b&gt;&lt;font color="#663300"&gt;
    }&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    else if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (((&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] &amp;gt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; 'A'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] &amp;lt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; 'Z'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)
              || (&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] &amp;gt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; 'a'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] &amp;lt;=&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; 'z'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;))
             &amp;amp;&amp;amp;&lt;/font&gt;&lt;/b&gt; utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;1&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] ==&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; ':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)
    {&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;
        /** OK -- drive letter -- unwind subst'ing */&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;
        for&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (;;)
        {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;
            wchar_t&lt;/font&gt; drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;3&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;];&lt;/font&gt;&lt;/b&gt;
            drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] = (&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;wchar_t&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;toupper&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;]);&lt;/font&gt;&lt;/b&gt;
            drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;1&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
            drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L'\0'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
            canon&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L'\0'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
            rc&lt;b&gt;&lt;font color="#663300"&gt; = ::&lt;/font&gt;&lt;/b&gt;QueryDosDeviceW&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;drive&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; MAX_PATH&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;rc&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
                break&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;wcsncmp&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;canon&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; L"\\??\\"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;))
            {&lt;/font&gt;&lt;/b&gt;
                utf16&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;canon&lt;b&gt;&lt;font color="#663300"&gt;+&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;) +&lt;/font&gt;&lt;/b&gt; std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);
            }&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            else&lt;/font&gt;&lt;i&gt;&lt;font color="#999999"&gt; // Not subst'd
&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;                break&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;
        }&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

        wchar_t&lt;/font&gt; drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;4&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;];&lt;/font&gt;&lt;/b&gt;
        drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] = (&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;wchar_t&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;toupper&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;0&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;]);&lt;/font&gt;&lt;/b&gt;
        drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;1&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; ':'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
        drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '\\'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
        drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;3&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '\0'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;

        rc&lt;b&gt;&lt;font color="#663300"&gt; = ::&lt;/font&gt;&lt;/b&gt;GetDriveTypeW&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;drive&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;

        if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;rc&lt;b&gt;&lt;font color="#663300"&gt; ==&lt;/font&gt;&lt;/b&gt; DRIVE_REMOTE&lt;b&gt;&lt;font color="#663300"&gt;)
        {&lt;/font&gt;&lt;/b&gt;
            DWORD bufsize&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; MAX_PATH&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

            /* QueryDosDevice and WNetGetConnection FORBID the
             * trailing slash; GetDriveType REQUIRES it.
             */&lt;/font&gt;&lt;/i&gt;
            drive&lt;b&gt;&lt;font color="#663300"&gt;[&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt;2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;] =&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '\0'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;

            rc&lt;b&gt;&lt;font color="#663300"&gt; = ::&lt;/font&gt;&lt;/b&gt;WNetGetConnectionW&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;drive&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;, &amp;amp;&lt;/font&gt;&lt;/b&gt;bufsize&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
            if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (&lt;/font&gt;&lt;/b&gt;rc&lt;b&gt;&lt;font color="#663300"&gt; ==&lt;/font&gt;&lt;/b&gt; NO_ERROR&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;
                utf16&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;canon&lt;b&gt;&lt;font color="#663300"&gt;) +&lt;/font&gt;&lt;/b&gt; std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#999900"&gt; 2&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);
        }
    }&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    else&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;
    {&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;
        // Not understood
&lt;/font&gt;&lt;/i&gt;&lt;font color="#ff0000"&gt;        return&lt;/font&gt; path&lt;b&gt;&lt;font color="#663300"&gt;;
    }&lt;/font&gt;&lt;/b&gt;&lt;i&gt;&lt;font color="#999999"&gt;

    /** Canonicalise case and 8.3-ness */&lt;/font&gt;&lt;/i&gt;
    rc&lt;b&gt;&lt;font color="#663300"&gt; = ::&lt;/font&gt;&lt;/b&gt;GetLongPathNameW&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf16&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; canon&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; MAX_PATH&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    if&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; (!&lt;/font&gt;&lt;/b&gt;rc&lt;b&gt;&lt;font color="#663300"&gt;)&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
        return&lt;/font&gt; path&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;

    std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;string utf8&lt;b&gt;&lt;font color="#663300"&gt; =&lt;/font&gt;&lt;/b&gt; UTF16ToUTF8&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;canon&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;
    std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;replace&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;utf8&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;begin&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; utf8&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;end&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '\\'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; '/'&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    return&lt;/font&gt; utf8&lt;b&gt;&lt;font color="#663300"&gt;;
}&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;There are still ways to fool this function: for instance, by
exporting a directory as &lt;nobr&gt;&lt;tt&gt;\\server\share1&lt;/tt&gt;&lt;/nobr&gt; and a
subdirectory of it as &lt;nobr&gt;&lt;tt&gt;\\server\share2&lt;/tt&gt;&lt;/nobr&gt; &amp;mdash;
the client has no way of matching them up. But that&amp;rsquo;s a pretty
pathological case, and it could be easily argued that it&amp;rsquo;s
something you&amp;rsquo;d never do unless you wanted the shares to appear
to be distinct. More seriously, the server for a network drive can be
specified by WINS name, by FQDN or by IP address; neither
canonicalise-to-IP nor canonicalise-to-FQDN is the Right Thing in all
cases. For now I&amp;rsquo;m sweeping that issue under the carpet.&lt;/p&gt;

&lt;p&gt;The one remaining wrinkle is that, unlike earlier versions of
Windows, Vista allows &amp;ldquo;genuine&amp;rdquo; Unix-like symbolic
links. Without doing real testing on Vista, it&amp;rsquo;s hard to make
out from the documentation how the APIs used above behave when faced
with such symbolic links. It&amp;rsquo;s even possible that the
new-in-Vista &lt;tt&gt;GetFinalPathNameByHandle()&lt;/tt&gt; call is the answer to
all these problems; in which case, this code gets demoted to merely
the way to do it on pre-Vista versions.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-7136550123655056089?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/7136550123655056089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7136550123655056089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7136550123655056089'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html' title='PathCanonicalize Versus What It Says On The Tin'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-3052891041590749887</id><published>2009-05-06T23:21:00.000+01:00</published><updated>2009-05-06T23:22:09.410+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><title type='text'>Unicode Is The One True God, And UTF-8 Is His Prophet</title><content type='html'>&lt;p&gt;One common anti-pattern in the Win32 API is the one whereby
something is done wrong the first time, then later re-implemented
properly &amp;mdash; but, for compatibility reasons, the older, broken
implementation can never actually be removed or fixed. (The
uncharitable might say that another common anti-pattern is the same
thing, but where the re-implementation doesn&amp;rsquo;t work either.)

&lt;p&gt;An example of one or both of these anti-patterns is encoding
support. The Win32 API&amp;rsquo;s Unicode support was invented before
UTF-8 was, so Microsoft can&amp;rsquo;t exactly be blamed for not using
UTF-8. Instead they used UCS-2 (later retconned to UTF-16), but, with
16-bit characters, this was grievously incompatible with Win16 &amp;mdash;
and, indeed, with all other C source in the world at that time. So
they kept an 8-bit-character &amp;ldquo;ANSI&amp;rdquo; API around as well,
compatible with the 8-bit code-pages of Win16.

&lt;p&gt;Without the same compatibility &lt;a
href="http://blogs.msdn.com/michkap/archive/2006/10/11/816996.aspx"&gt;millstone&lt;/a&gt;
around its neck, Linux (eventually) embraced UTF-8 into its locale
system, to the extent that nowadays it&amp;rsquo;s reasonable to describe
all non-UTF-8 locales as &amp;ldquo;legacy&amp;rdquo;. When writing portable
software (location-portable as well as system-portable) for Linux,
it&amp;rsquo;s quite the natural thing to do to store all text in UTF-8,
and, if happening to find oneself running in a legacy locale, to
translate to UTF-8 on the way in and from UTF-8 on the way out. That
way, almost all the code can just deal with normal &lt;tt&gt;char*&lt;/tt&gt; and
assume it&amp;rsquo;s encoded in UTF-8.

&lt;p&gt;And then eventually you&amp;rsquo;re going to want to port that software to
Windows &amp;mdash; whereupon you&amp;rsquo;ve got a problem.

&lt;p&gt;Indeed, you have a whole little family of problems, and
they&amp;rsquo;ve got names such as &lt;tt&gt;fopen&lt;/tt&gt;, &lt;tt&gt;rename&lt;/tt&gt;,
&lt;tt&gt;unlink&lt;/tt&gt;, and more. All of these calls &amp;mdash; and those are
just the ISO C ones; Posix and C++ add more &amp;mdash; take 8-bit strings
as filename arguments, and, in Windows, there are some files that this
just won&amp;rsquo;t let you see. Files in Windows filesystems have UTF-16
names, which, when you use 8-bit calls, are mapped down into the
characters available in the current ANSI code-page. (Strictly
speaking, the code-page set as the &amp;ldquo;Code-page for non-Unicode
applications&amp;rdquo; in Control Panel.)

&lt;p&gt;So suppose you have your code-page for non-Unicode applications set
to CP1252 for generic Western European, and your Greek friend, who has
his code-page for non-Unicode applications set to CP1253 for Greek,
writes two files with Greek names onto a USB stick and hands it to
you. The filenames will be stored as UTF-16, featuring characters
which do not exist in your code-page. And if you have two files whose
names are only distinguishable by characters not in your code-page,
you can&amp;rsquo;t distinguish them &amp;mdash; they&amp;rsquo;ll both come back
as, say, &amp;ldquo;????.txt&amp;rdquo;, and, while there&amp;rsquo;s enough grody
hacks in Windows that &lt;tt&gt;fopen&lt;/tt&gt; &lt;i&gt;will&lt;/i&gt; actually open
&amp;ldquo;????.txt&amp;rdquo;, that still only gets you one of the two
files. There&amp;rsquo;s no way of opening the other one using 8-bit
calls.

&lt;p&gt;There&amp;rsquo;s only a few things you can do about this. The easiest,
certainly, is to ignore it completely &amp;mdash; after all, most people
only create files named in their own language. This is the position
taken by Cygwin (before 1.7, anyway) and thus, implicitly, by all Unix
software which has been ported to Windows by simply recompiling it
against Cygwin &lt;font size=-2&gt;mentioning no names&lt;/font&gt;. It is, of
course, very &lt;a
href="http://www.ommatidia.org/2009/04/28/emdash/"&gt;unsatisfactory&lt;/a&gt;
&amp;mdash; for instance, among non-Czechs partial to MP3s of music
composed by Anton&amp;iacute;n Dvo&lt;b&gt;&amp;#345;&lt;/b&gt;&amp;aacute;k.

&lt;p&gt;Alternatively, you could go through all your code replacing all the
strings used to keep filenames in with wide-strings, all the calls to
&lt;tt&gt;fopen&lt;/tt&gt; with &lt;tt&gt;_wfopen&lt;/tt&gt;, and so on &amp;mdash; or use all the
ugly macros such as &lt;tt&gt;_tfopen&lt;/tt&gt; (which was the Microsoft advice
even for Windows-only programs, back in the day when Windows 95 was
Win32 but not Unicode, so it was common to make two binary builds of
the same sources). But this is a lot of work &amp;mdash; and error-prone,
particularly if you rely on other libraries that have been ported to
Windows using the &lt;i&gt;ignore-the-problem&lt;/i&gt; technique, and you thus
have to go and update them too.

&lt;p&gt;Fortunately, there&amp;rsquo;s another way of solving the problem
&amp;mdash; at least, if you&amp;rsquo;re targetting Windows using &lt;a
href="http://www.mingw.org/"&gt;Mingw&lt;/a&gt; and are thus using the GNU
binutils linker. If you add

&lt;blockquote&gt;&lt;tt&gt;-Wl,--wrap,fopen -Wl,--wrap,rename -Wl,--wrap,unlink&lt;/tt&gt; &lt;i&gt;&amp;hellip; etc.&lt;/i&gt;&lt;/blockquote&gt;

to the linker command-line, all calls to (for instance) &lt;tt&gt;fopen&lt;/tt&gt;
will be &lt;a
href="http://sourceware.org/binutils/docs-2.19/ld/Options.html#index-g_t_002d_002dwrap-249"&gt;converted&lt;/a&gt;
into calls to &lt;tt&gt;__wrap_fopen&lt;/tt&gt;, which you can implement in your
own code. In particular, you can make it do something like this:

&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;
&lt;blockquote&gt;
&lt;pre&gt;&lt;font color="#990000"&gt;extern&lt;/font&gt;&lt;font color="#009900"&gt; "C"&lt;/font&gt; FILE&lt;b&gt;&lt;font color="#663300"&gt;*&lt;/font&gt;&lt;/b&gt; __cdecl __wrap_fopen&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt;&lt;font color="#ff6633"&gt; char&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;path&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; const&lt;/font&gt;&lt;font color="#ff6633"&gt; char&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;mode&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt;
    std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring wpath&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; wmode&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
    util&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;UTF8ToWide&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;path&lt;b&gt;&lt;font color="#663300"&gt;, &amp;amp;&lt;/font&gt;&lt;/b&gt;wpath&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;
    util&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;UTF8ToWide&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;mode&lt;b&gt;&lt;font color="#663300"&gt;, &amp;amp;&lt;/font&gt;&lt;/b&gt;wmode&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    return&lt;/font&gt; _wfopen&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;wpath&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; wmode&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;());
}&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

extern&lt;/font&gt;&lt;font color="#009900"&gt; "C"&lt;/font&gt;&lt;font color="#ff6633"&gt; int&lt;/font&gt; __cdecl __wrap_rename&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt;&lt;font color="#ff6633"&gt; char&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;oldname&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; const&lt;/font&gt;&lt;font color="#ff6633"&gt; char&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;newname&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt;
    std&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;wstring woldname&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; wnewname&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;
    util&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;UTF8ToWide&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;oldname&lt;b&gt;&lt;font color="#663300"&gt;, &amp;amp;&lt;/font&gt;&lt;/b&gt;woldname&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;
    util&lt;b&gt;&lt;font color="#663300"&gt;::&lt;/font&gt;&lt;/b&gt;UTF8ToWide&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;newname&lt;b&gt;&lt;font color="#663300"&gt;, &amp;amp;&lt;/font&gt;&lt;/b&gt;wnewname&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt;
    return&lt;/font&gt; _wrename&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;woldname&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;(),&lt;/font&gt;&lt;/b&gt; wnewname&lt;b&gt;&lt;font color="#663300"&gt;.&lt;/font&gt;&lt;/b&gt;c_str&lt;b&gt;&lt;font color="#663300"&gt;());
}&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;(You don&amp;rsquo;t, of course, get prototypes for
&lt;tt&gt;__wrap_fopen&lt;/tt&gt; or &lt;tt&gt;__wrap_rename&lt;/tt&gt;, so you must carefully
ensure to give them the same signatures as the genuine functions.)
This way, all your code can carry on using UTF-8 filenames everywhere,
passing them to system calls such as &lt;tt&gt;fopen&lt;/tt&gt;, and even passing
them to external libraries, so long as you&amp;rsquo;ve wrapped the calls
the libraries themselves make. (Which you can check by asking the
linker for a map file: &lt;tt&gt;-Wl,-Map,map.txt&lt;/tt&gt;.)

&lt;p&gt;Naturally, there&amp;rsquo;s no point using ANSI Win32 APIs in
Windows-specific parts of your code, only to then wrap them &amp;mdash; it
only makes sense there to go straight for the UTF-16 ones (with the W
on the end, such as &lt;tt&gt;RegQueryValueExW&lt;/tt&gt;) to start with. This
wrapping technique is a way of avoiding rewriting the existing
&lt;em&gt;portable&lt;/em&gt; parts of your code.

&lt;p&gt;It&amp;rsquo;s like having an ANSI code-page of UTF-8 all to your very
own.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-3052891041590749887?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/3052891041590749887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/05/unicode-is-one-true-god-and-utf-8-is.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/3052891041590749887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/3052891041590749887'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/05/unicode-is-one-true-god-and-utf-8-is.html' title='Unicode Is The One True God, And UTF-8 Is His Prophet'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-6740355075673737142</id><published>2009-04-23T18:58:00.000+01:00</published><updated>2009-05-06T12:41:37.554+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>One Template To Rule Them All</title><content type='html'>&lt;p&gt;How do you write a template that can be instantiated for
&lt;em&gt;any&lt;/em&gt; type?  Here&amp;rsquo;s a header file which purports to implement a
tracing (logging) mechanism...

&lt;blockquote&gt;
&lt;!-- To generate your own colored code visit http://www.bedaux.net/cpp2html/ --&gt;
&lt;pre&gt;&lt;font color="#000099"&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/font&gt;&lt;font color="#990000"&gt;
class&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt; {};&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

inline const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; operator&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;lt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; r&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt; int&lt;/font&gt; i&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt; printf&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt;"%d"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; i&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt; r&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

inline const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; operator&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;lt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; r&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; const&lt;/font&gt;&lt;font color="#ff6633"&gt; char&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;s&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt; printf&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt;"%s"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; s&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt; r&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; T&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
inline const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; operator&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;lt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; Tracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; r&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; T&lt;b&gt;&lt;font color="#663300"&gt; *&lt;/font&gt;&lt;/b&gt;p&lt;b&gt;&lt;font color="#663300"&gt;)
{&lt;/font&gt;&lt;/b&gt; printf&lt;b&gt;&lt;font color="#663300"&gt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt;"%p"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; p&lt;b&gt;&lt;font color="#663300"&gt;);&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt; r&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

class&lt;/font&gt; NullTracer&lt;b&gt;&lt;font color="#663300"&gt; {};&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

template&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;typename&lt;/font&gt; T&lt;b&gt;&lt;font color="#663300"&gt;&amp;gt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
inline const&lt;/font&gt; NullTracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; operator&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;lt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; NullTracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; n&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; T&lt;b&gt;&lt;font color="#663300"&gt;) {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt; n&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;&lt;font color="#000099"&gt;

#ifdef DEBUG
#define TRACE Tracer()
#else
#define TRACE NullTracer()
#endif
&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;...and here&amp;rsquo;s some example client code:

&lt;blockquote&gt;&lt;pre&gt;&lt;font color="#990000"&gt;class&lt;/font&gt; X&lt;b&gt;&lt;font color="#663300"&gt;
{&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;
    enum&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; {&lt;/font&gt;&lt;/b&gt; A&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt; B&lt;b&gt;&lt;font color="#663300"&gt; }&lt;/font&gt;&lt;/b&gt; m_state&lt;b&gt;&lt;font color="#663300"&gt;;&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt;

    void&lt;/font&gt; Foo&lt;b&gt;&lt;font color="#663300"&gt;() {&lt;/font&gt;&lt;/b&gt; TRACE&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; "x"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; this&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; " is in state "&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&amp;lt;&lt;/font&gt;&lt;/b&gt; m_state&lt;b&gt;&lt;font color="#663300"&gt; &amp;lt;&amp;lt;&lt;/font&gt;&lt;/b&gt;&lt;font color="#009900"&gt; "\n"&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;

public&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;:&lt;/font&gt;&lt;/b&gt;
    X&lt;b&gt;&lt;font color="#663300"&gt;();
};&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;(I used &lt;a href="http://www.bedaux.net/cpp2html/"&gt;this&lt;/a&gt; rather nifty
script to do the syntax-colouring.)

&lt;p&gt;What&amp;rsquo;s going on here is that, in debug builds (with
&lt;tt&gt;-DDEBUG&lt;/tt&gt; on the compiler command-line), &lt;tt&gt;TRACE&lt;/tt&gt; expands
to an expression that creates an object that acts a bit like
&lt;tt&gt;std::cout&lt;/tt&gt;, in that various different types of object can be
sent to it and each printed in a sensible and type-safe manner. Just
as with &lt;tt&gt;std::cout&lt;/tt&gt;, the precedence and associativity of the
&lt;tt&gt;&amp;lt;&amp;lt;&lt;/tt&gt; operator get everything printed in the right order.

&lt;p&gt;In release builds, meanwhile, &lt;tt&gt;TRACE&lt;/tt&gt; expands to an
expression that creates an object of a different class, whose
&lt;tt&gt;operator&amp;lt;&amp;lt;&lt;/tt&gt; ensures that whatever type is sent to it,
nothing is printed &amp;mdash; and, indeed, the entire expression
optimises away to nothing.

&lt;p&gt;Except there&amp;rsquo;s a problem. The code above doesn&amp;rsquo;t actually compile
in release builds (without &lt;tt&gt;-DDEBUG&lt;/tt&gt;). Here&amp;rsquo;s what GCC 4.3.3
says about it:
&lt;blockquote&gt;
&lt;tt&gt;&lt;font color=blue&gt;wtf.cpp: In member function &amp;lsquo;void X::Foo()&amp;rsquo;:&lt;/font&gt;&lt;br&gt;
&lt;font color=red&gt;wtf.cpp:30: error: no match for
&amp;lsquo;operator&amp;lt;&amp;lt;&amp;rsquo; in &amp;lsquo;operator&amp;lt;&amp;lt; [with T = const char*](((const NullTracer&amp;amp;)((const NullTracer*)operator&amp;lt;&amp;lt;
[with T = X*](((const NullTracer&amp;amp;)((const NullTracer*)operator&amp;lt;&amp;lt;
[with T = const char*](((const NullTracer&amp;amp;)((const NullTracer*)(&amp;amp; NullTracer()))),
((const char*)&amp;quot;x&amp;quot;)))), this))), ((const char*)&amp;quot; is in state &amp;quot;)) &amp;lt;&amp;lt;
((X*)this)-&gt;X::m_state&amp;rsquo;&lt;/font&gt;&lt;br&gt;

&lt;font color=blue&gt;wtf.cpp:10: note: candidates are: const Tracer&amp; operator&lt;&lt;(const Tracer&amp;, int)&lt;br&gt;
wtf.cpp:13: note:                 const Tracer&amp; operator&lt;&lt;(const Tracer&amp;, const char*)&lt;/font&gt;&lt;/tt&gt;

&lt;/blockquote&gt;

&lt;p&gt;So naturally I knew at once what the problem was. &lt;em&gt;Not&lt;/em&gt;. The
error suggests that it can&amp;rsquo;t find an &lt;tt&gt;operator&amp;lt;&amp;lt;&lt;/tt&gt; to do
the job &amp;mdash; but surely there&amp;rsquo;s one right there that can do any
such job. Yet it isn&amp;rsquo;t even listed as a candidate.

&lt;p&gt;While composing my GCC Bugzilla entry in my head, I tried to
whittle down the problem. To my surprise, it was the enum which was
causing the problem: trace statements with only strings and pointers
compiled just fine. (Those experienced with what &lt;a
href="http://www.amazon.co.uk/Template-Metaprogramming-Concepts-Techniques-Beyond/dp/0321227255"&gt;Abrahams
and Gurtovoy&lt;/a&gt; call &amp;ldquo;debugging the error novel&amp;rdquo; might
just about be able to make that out from the error message.)

&lt;p&gt;So what&amp;rsquo;s up with &lt;tt&gt;m_state&lt;/tt&gt;? What&amp;rsquo;s so very special about
its type that it isn&amp;rsquo;t matched by
&lt;tt&gt;template&amp;lt;typename&amp;nbsp;T&amp;gt;&lt;/tt&gt;? Well, there is one special
thing about its type. It&amp;rsquo;s &lt;em&gt;unnamed&lt;/em&gt;. When I wrote
&lt;tt&gt;m_state&lt;/tt&gt; into that code, neither its declaration, nor any of
its uses, actually needed to name its type &amp;mdash; so I applied
Occam&amp;rsquo;s Razor and didn&amp;rsquo;t give it a name. And it turns out that that&amp;rsquo;s
the problem: &lt;em&gt;you can&amp;rsquo;t instantiate a template with an unnamed type
as a template-argument&lt;/em&gt;. I can&amp;rsquo;t find a statement to that effect
in &lt;a
href="http://www.amazon.co.uk/C-Programming-Language-Third/dp/0201889544"&gt;Stroustrup-3&lt;/a&gt;,
but it&amp;rsquo;s right there in the ISO&amp;nbsp;C++03 standard ISO/IEC&amp;nbsp;14882:2003 at 14.3.1
[temp.arg.type]:

&lt;blockquote&gt;A local type, a type with no linkage, an unnamed type or a
type compounded from any of these types shall not be used as a
&lt;em&gt;template-argument&lt;/em&gt; for a template &lt;em&gt;type-parameter&lt;/em&gt;.
&lt;/blockquote&gt;

&lt;p&gt;This does make perfect sense when you think about it a bit more: if
templates could be instantiated with unnamed types, how would their
names be &lt;a
href="http://en.wikipedia.org/wiki/Name_mangling"&gt;mangled&lt;/a&gt;? Or, in
other words, how could the compiler and linker conspire to arrange
that multiple instantiations of
&lt;tt&gt;NullTracer&amp;lt;&lt;/tt&gt;&lt;em&gt;unnamed-enum-type&lt;/em&gt;&lt;tt&gt;&amp;gt;&lt;/tt&gt;, in
multiple translation units, ended up as one instantiation in the final
program? Without name matching, there&amp;rsquo;d be no way to do that &amp;mdash;
at least within the constraints that the C++ committee set for
themselves, specifically that C++ compilers be usable with C-era
linkers by dint of name mangling. The same mangling considerations are
probably also the reasoning behind the ban on string literals as template
arguments.

&lt;p&gt;And the reason it works in non-debug builds, with the real
&lt;tt&gt;Tracer&lt;/tt&gt;, is that in that case no template is instantiated with
&lt;tt&gt;m_state&lt;/tt&gt;&amp;rsquo;s actual type: integral promotion makes it an
&lt;tt&gt;int&lt;/tt&gt;, and the overload for &lt;tt&gt;int&lt;/tt&gt; is called. Nor can you
fix up &lt;tt&gt;NullTracer&lt;/tt&gt; by adding a template specialisation for
&lt;tt&gt;int&lt;/tt&gt;: the template specialisation rules aren&amp;rsquo;t quite the same
as the overload resolution rules, and the compiler is doomed to pick
the generic &lt;tt&gt;operator&amp;lt;&amp;lt;&lt;/tt&gt;, and have it fail,
&lt;em&gt;before&lt;/em&gt; it tries the integral promotions. (&lt;a
href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error"&gt;SFINAE&lt;/a&gt;
doesn&amp;rsquo;t help us, as again it is applied only with the enum type, not
the promoted type.)

&lt;p&gt;So what's needed is another overload, one that catches unnamed enum types:

&lt;blockquote&gt;&lt;pre&gt;&lt;font color="#990000"&gt;inline const&lt;/font&gt; NullTracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt; operator&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;&amp;lt;&amp;lt;(&lt;/font&gt;&lt;/b&gt;&lt;font color="#990000"&gt;const&lt;/font&gt; NullTracer&lt;b&gt;&lt;font color="#663300"&gt;&amp;amp;&lt;/font&gt;&lt;/b&gt; n&lt;b&gt;&lt;font color="#663300"&gt;,&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff6633"&gt; int&lt;/font&gt;&lt;b&gt;&lt;font color="#663300"&gt;) {&lt;/font&gt;&lt;/b&gt;&lt;font color="#ff0000"&gt; return&lt;/font&gt; n&lt;b&gt;&lt;font color="#663300"&gt;; }&lt;/font&gt;&lt;/b&gt;
&lt;/pre&gt;&lt;/blockquote&gt;

And now everything works as expected: unnamed enums (and, in fact,
ints too, not that it matters) are passed via the non-templated
overload, and everything else goes via the templated overload.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-6740355075673737142?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/6740355075673737142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/04/one-template-to-rule-them-all.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6740355075673737142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/6740355075673737142'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/04/one-template-to-rule-them-all.html' title='One Template To Rule Them All'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-8407361893313459858</id><published>2009-04-15T16:56:00.000+01:00</published><updated>2009-04-15T16:58:17.247+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><title type='text'>Debugging The Invisible</title><content type='html'>&lt;p&gt;The Empeg codebase, and the Empeg coding style for embedded C++, don&amp;rsquo;t
use C++ exceptions. The original reason was that ARM support in GCC
was still a bit sketchy when Empeg started, and exceptions plain
didn&amp;rsquo;t work.

&lt;p&gt;But I think that even with a toolchain in which C++ exceptions work
properly, they should still be avoided, and not just in
&lt;em&gt;embedded&lt;/em&gt; systems either. Here&amp;rsquo;s why.


&lt;h3&gt;Exception safety&lt;/h3&gt;

&lt;p&gt;You need to write your code in &lt;em&gt;exception-safe style&lt;/em&gt;: a style
which neither the compiler, nor other tools, can enforce. Some would
say that &amp;ldquo;write exception-safe code&amp;rdquo; is just another way
of saying &amp;ldquo;don&amp;rsquo;t write buggy code&amp;rdquo;, or
&amp;ldquo;don&amp;rsquo;t be a crap programmer&amp;rdquo;, but many other ways of
saying that &amp;mdash; &amp;ldquo;write const-correct code&amp;rdquo;,
&amp;ldquo;don&amp;rsquo;t leak memory&amp;rdquo; &amp;mdash; can be automatically
checked, and thus a unit-test suite (perhaps with &lt;a
href="http://www.valgrind.org"&gt;Valgrind&lt;/a&gt;) can give you great
confidence that your code fulfils those criteria, and remains in
fulfilment under subsequent maintenance. You can&amp;rsquo;t easily
unit-test for exception safety.

&lt;p&gt;Another consideration is that many, perhaps most, C++ developers used
to be C developers. Most things these developers need to learn when
switching to C++, are completely new things. But exception-safety is
something they need to learn which changes the way they&amp;rsquo;d write
perfectly reasonable straight-line C code, so that&amp;rsquo;s always going to
be trickier for everyone.

&lt;p&gt;Scott Meyers didn&amp;rsquo;t even bother writing exception-safe code until
&lt;a href="http://www.aristeia.com/BookErrata/ec++2e-errata.html"&gt;the
&lt;em&gt;third&lt;/em&gt; edition of Effective C++&lt;/a&gt; (search for &amp;ldquo;dfc&amp;rdquo;).


&lt;h3&gt;Invisible control flow&lt;/h3&gt;

&lt;p&gt;The Empeg C++ coding style, like others, forbade non-const reference
parameters. The reason is, that doing so forces by-reference objects
which may be modified to go via pointers instead. This, in turn,
forces call sites to use &amp;ldquo;&amp;amp;&amp;rdquo; when a function may
modify the value, and no &amp;ldquo;&amp;amp;&amp;rdquo; when it
doesn&amp;rsquo;t. This puts this essential information about the data
flow at the call site, not just at the declaration &amp;mdash; and, when
debugging, it&amp;rsquo;s usually the call site and not the declaration
that you&amp;rsquo;re looking at. So banning non-const references improves
the understandability of the data flow by making it visible.

&lt;p&gt;Exceptions are, in a way, even &lt;em&gt;worse&lt;/em&gt; than non-const
references: they bestow on your code unasked, not just data flow you
can&amp;rsquo;t see, but &lt;em&gt;control&lt;/em&gt; flow you can&amp;rsquo;t
see. Consider, in particular, a function that doesn&amp;rsquo;t contain a
&lt;tt&gt;try&lt;/tt&gt; or a &lt;tt&gt;throw&lt;/tt&gt;, but calls functions which do (or
&lt;em&gt;may&lt;/em&gt; do). There&amp;rsquo;s a second control flow through all that
code, which you didn&amp;rsquo;t write &amp;mdash; the one where something
below it in the call-chain throws, and something above it catches
&amp;mdash; but which has a crucial effect on whether your code is buggy
or not.

&lt;p&gt;And again, you can&amp;rsquo;t unit-test for it: even if you use gcov to test
that your tests cover the normal control flow of your code, it can&amp;rsquo;t
tell you whether you&amp;rsquo;ve also exercised all the invisible, secondary
control flows. (In theory, a much smarter gcov-like tool could,
though.)

&lt;p&gt;&lt;a href="http://www.joelonsoftware.com/items/2003/10/13.html"&gt;Joel
agrees&lt;/a&gt;.

&lt;h3&gt;Speed, size, exceptions: pick two&lt;/h3&gt;

&lt;p&gt;In &lt;a
href="http://en.wikipedia.org/wiki/The_Design_and_Evolution_of_C%2B%2B"&gt;D&amp;amp;E&lt;/a&gt;,
Stroustrup that claims a design goal for C++ exceptions was &amp;ldquo;No
added cost (in time or space) to code that does not throw an
exception&amp;rdquo; (16.2), but later on in 16.9.1 he admits that people
have figured out how to avoid cost in time in the no-exception case,
but not cost in space.

&lt;p&gt;A medium-sized C++ program I have here (amd64-linux, GCC 4.3.2) has
a text section of 548K and exception-handling tables of 127K. But even
that 23% increase isn&amp;rsquo;t the whole story, as is revealed by
disassembly: that try-less, throw-less, but non-leaf function &amp;mdash;
if it has local variables with destructors &amp;mdash; also gains &lt;a
href="http://gcc.gnu.org/ml/gcc/2009-04/msg00266.html"&gt;snippets of
unwinding code&lt;/a&gt; for each such variable. These snippets appear in
the text section, so can&amp;rsquo;t easily be totalled-up, but an
unscientific test on one source file suggests that they make up about
7% of the text section.

&lt;p&gt;These exception-handling tables do affect embedded systems more than
desktops or servers &amp;mdash; on which the exception-handling tables are
never demand-paged in unless they&amp;rsquo;re used &amp;mdash; but the unwinding
snippets are still there affecting your paging bandwidth and filling
your instruction cache.

&lt;h3&gt;But you don&amp;rsquo;t get to choose&lt;/h3&gt;

&lt;p&gt;In a sense, choosing which of the two distinct languages &amp;mdash;
C++-with-exceptions or C++-without-exceptions &amp;mdash; to use to
program your embedded system, is a choice you only get to make when
starting the system from scratch. Or, at least, converting a codebase
from C++-without-exceptions to C++-with-exceptions is a herculean and
error-prone task, and a half-converted one is a bug tarpit, because of
the exception-safety issues. If the actual goal is to use a library
written in C++-with-exceptions with a main program written in
C++-without-exceptions, the best way is to write wrappers for each
library function, that &lt;tt&gt;catch(...)&lt;/tt&gt; and report errors through
the existing non-exception error handling mechanism. With a bit of
luck you can then continue to compile the main program with
&lt;tt&gt;-fno-exceptions&lt;/tt&gt; (or similar) and avoid the space overhead.

&lt;p&gt;Even this doesn&amp;rsquo;t really work when the library is something like &lt;a
href="http://www.boost.org"&gt;Boost&lt;/a&gt;, which is chock-full of throws
in headers that really you need to be including in any code that uses
the library. (Including for things like locking a non-recursive mutex
that&amp;rsquo;s already locked, which in my book is more like a programming
error than an exceptional condition, and would be better as an
assertion. But that&amp;rsquo;s a different rant.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-8407361893313459858?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/8407361893313459858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/04/debugging-invisible.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/8407361893313459858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/8407361893313459858'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/04/debugging-invisible.html' title='Debugging The Invisible'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5280200963174451807.post-7572644537844388506</id><published>2009-04-12T20:24:00.000+01:00</published><updated>2009-04-15T17:15:17.597+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snippet'/><category scheme='http://www.blogger.com/atom/ns#' term='geeky'/><category scheme='http://www.blogger.com/atom/ns#' term='configury'/><title type='text'>Autoconf, #ifdef, and #if</title><content type='html'>&lt;p&gt;The standard macros available in &lt;a href="http://www.gnu.org/software/autoconf/"&gt;GNU Autoconf&lt;/a&gt; for &amp;ldquo;checking for...&amp;rdquo; C/C++ functions and header files, AC_CHECK_FUNCS and AC_CHECK_HEADERS, have a couple of things going for them: their syntax and semantics essentially haven&amp;rsquo;t changed for years, perhaps ever, and everyone &amp;mdash; well, everyone &lt;span style="font-style: italic;"&gt;who writes configure scripts&lt;/span&gt;, which if it isn&amp;rsquo;t you should be a big hint as to how much you&amp;rsquo;ll get from this blog &amp;mdash; already knows how they work. Which is to say, they end up embedding in your generating header, typically &lt;tt&gt;config.h&lt;/tt&gt;, lines which look like this:&lt;blockquote&gt;&lt;pre&gt;/* Define to 1 if you have the &amp;lt;linux/inotify.h&amp;gt; header file. */
/* #undef HAVE_LINUX_INOTIFY_H */

/* Define to 1 if you have the `localtime_r' function. */
#define HAVE_LOCALTIME_R 1&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;That&amp;rsquo;s all you need to start making your code conditional on which facilities are available:
&lt;blockquote&gt;&lt;pre&gt;#include "config.h"
    [...]
#ifdef HAVE_LOCALTIME_R
    localtime_r(&amp;amp;start, &amp;amp;stm);
#else
    // This code isn't thread-safe and could
    // get the wrong time -- but the result
    // would just be an odd-looking filename, not 
    // incorrect operation, so we live with it
    stm = *localtime(&amp;amp;start);
#endif&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;But there&amp;rsquo;s a problem. In fact, there&amp;rsquo;re two problems. One of the best features of C and C++, one of the few things that lets the old guard lord it over today&amp;rsquo;s arriviste scripting languages, the pythons and the rubies, is that almost everything is checked at compile-time. If you mistype an identifier, say &lt;tt&gt;localtime_r&lt;/tt&gt;, as &lt;tt&gt;localtimer&lt;/tt&gt; or whatever else, your code won&amp;rsquo;t compile, even if it&amp;rsquo;s on a rarely- or never-used path through the code. Unless you&amp;rsquo;re unlucky enough to hit the exact name of another existing identifier (and even then the type system may save you, unless you&amp;rsquo;re unlucky &lt;span style="font-style: italic;"&gt;again&lt;/span&gt;), your mistyping is caught right there as you&amp;rsquo;re writing the code, not in QA &amp;mdash; or, horrors, in production.

&lt;p&gt;The same can&amp;rsquo;t be said, though, of identifiers in &lt;tt&gt;#ifdef&lt;/tt&gt;. It&amp;rsquo;s perfectly valid to use a name there that doesn&amp;rsquo;t exist &amp;mdash; nor could it be otherwise, as there&amp;rsquo;s nothing else it &lt;span style="font-style: italic;"&gt;does&lt;/span&gt; except distinguish existent from non-existent names. So if you fat-finger it &amp;mdash; HAVE_LOCALTIMER, maybe &amp;mdash; the code compiles without even a warning, and just does the wrong thing, or at least the less-optimal thing. Even into production.

&lt;p&gt;The second problem is &lt;tt&gt;config.h&lt;/tt&gt; itself: if you forget to &lt;tt&gt;#include&lt;/tt&gt; it, again your code compiles without a warning, but all your features get turned off! There are ways around this, such as by having a little script that checks your sources using grep, or by using GCC&amp;rsquo;s &lt;tt&gt;-include&lt;/tt&gt; command-line option to force the inclusion, but none is ideal. (For instance, the latter gets dependencies wrong if &lt;tt&gt;config.h&lt;/tt&gt; changes.)

&lt;p&gt;Really what you want is&lt;span style="font-style: italic;"&gt; warnings at compile-time&lt;/span&gt; if you mistype the identifier, or forget the header. In order to do this, you&amp;rsquo;re going to need to use &lt;tt&gt;#if&lt;/tt&gt; rather than &lt;tt&gt;#ifdef&lt;/tt&gt;; in other words, you&amp;rsquo;re going to need a config.h with lines like this:
&lt;blockquote&gt;&lt;pre&gt;/* Define to 1 if you have &amp;lt;linux/inotify.h&amp;gt;, or to 0 if you don't. */
#define HAVE_LINUX_INOTIFY_H 0

/* Define to 1 if you have localtime_r(), or to 0 if you don't. */
#define HAVE_LOCALTIME_R 1&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And to do &lt;span style="font-style: italic;"&gt;that&lt;/span&gt;, you&amp;rsquo;re going to have to use custom Autoconf macros instead of the standard AC_CHECK_ ones. Which is the point at which most people would give up, as Autoconf macros expand into shell code but are themselves written in the macro language m4, whose syntax can be charitably described as quixotic, and is regularly described using rather shorter and more Anglo-Saxon words than that. So here, I&amp;rsquo;ve done it for you, have these ones:
&lt;blockquote&gt;&lt;pre&gt;AC_DEFUN([PDH_CHECK_HEADER], [
AC_MSG_CHECKING([for &lt;$1&gt;])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include &lt;$1&gt;
]])],
          [AC_MSG_RESULT([yes]); pdh_haveit=1; pdh_yesno="yes"],
          [AC_MSG_RESULT([no]);  pdh_haveit=0; pdh_yesno="no"])
AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), $pdh_haveit,
          [Define to 1 if you have &lt;$1&gt;, or to 0 if you don't.])
AS_TR_SH([ac_cv_header_$1])=$pdh_yesno
])

AC_DEFUN([PDH_CHECK_HEADERS], [
m4_foreach_w([pdh_header], $1, [PDH_CHECK_HEADER(pdh_header)])
])

AC_DEFUN([PDH_CHECK_FUNC], [
AC_MSG_CHECKING([for $1()])
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[(void)$1();]])],
        [AC_MSG_RESULT([yes]); pdh_haveit=1; pdh_yesno="yes"],
        [AC_MSG_RESULT([no]);  pdh_haveit=0; pdh_yesno="no"])
AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), $pdh_haveit,
        [Define to 1 if you have $1(), or to 0 if you don't.])
AS_TR_SH([ac_cv_func_$1])=$pdh_yesno
])

AC_DEFUN([PDH_CHECK_FUNCS], [
m4_foreach_w([pdh_func], $1, [PDH_CHECK_FUNC(pdh_func)])
])&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;That bracketfest defines macros PDH_CHECK_HEADERS and PDH_CHECK_FUNCS which do the same job as the standard AC_CHECK_HEADERS and AC_CHECK_FUNCS...

&lt;blockquote&gt;&lt;tt&gt;PDH_CHECK_HEADERS([io.h poll.h errno.h fcntl.h sched.h net/if.h stdint.h stdlib.h unistd.h shlwapi.h pthread.h ws2tcpip.h sys/poll.h sys/time.h sys/types.h sys/socket.h sys/syslog.h netinet/in.h netinet/tcp.h sys/inotify.h sys/resource.h linux/unistd.h linux/inotify.h linux/dvb/dmx.h linux/dvb/frontend.h])

&lt;p&gt;PDH_CHECK_FUNCS([mkstemp localtime_r setpriority getaddrinfo inotify_init gettimeofday gethostbyname_r sync_file_range sched_setscheduler])
&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;...but leave you with identifiers in config.h that you can use &lt;tt&gt;#if&lt;/tt&gt; on rather than &lt;tt&gt;#ifdef&lt;/tt&gt;, so you can enjoy compile-time warnings if you get any of them wrong.

&lt;p&gt;Ah, except you can&amp;rsquo;t just yet, because there&amp;rsquo;s one final wrinkle. The C and C++ standards allow undefined identifiers in &lt;tt&gt;#if&lt;/tt&gt; just as in &lt;tt&gt;#ifdef&lt;/tt&gt; &amp;mdash; they don&amp;rsquo;t expand to nothing, giving the syntax errors you&amp;rsquo;d initially hope for, but are defined as evaluating to zero. So, back to square one. Except, fortunately, the authors of GCC appear to be as sceptical about the usefulness of that preprocessor feature as I am, and they provide an optional warning which can be emitted whenever the preprocessor is obliged to evaluate an undefined identifier as zero: &lt;tt&gt;-Wundef&lt;/tt&gt;. So, if you use the configury macros above, &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; add &lt;tt&gt;-Wundef&lt;/tt&gt; to your GCC command-lines, you can at last get the compiler to point it out to you when you mistype your configure macros.

&lt;p&gt;When I wrote these new macros, I did have a nagging feeling that it was all just NIH syndrome, and that it was silly makework to be rewriting core bits of Autoconf for this marginal benefit. But once I&amp;rsquo;d done it, re-compiling Chorale showed up two warnings, both places where a mistyped identifier was causing real and otherwise hard-to-find problems. So I felt retrospectively justified in my tinkering. The moral of the story: if you&amp;rsquo;ve fixed a bug, you&amp;rsquo;ve done a day&amp;rsquo;s work; but if you&amp;rsquo;ve fixed a bug by ensuring that it, and its whole class of fellow bugs, can never happen undetected again &amp;mdash; then, you&amp;rsquo;ve done a &lt;span style="font-style: italic;"&gt;good&lt;/span&gt; day&amp;rsquo;s work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5280200963174451807-7572644537844388506?l=pdh11.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pdh11.blogspot.com/feeds/7572644537844388506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://pdh11.blogspot.com/2009/04/standard-macros-available-in-gnu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7572644537844388506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5280200963174451807/posts/default/7572644537844388506'/><link rel='alternate' type='text/html' href='http://pdh11.blogspot.com/2009/04/standard-macros-available-in-gnu.html' title='Autoconf, #ifdef, and #if'/><author><name>Peter Hartley</name><uri>http://www.blogger.com/profile/02928051743675376830</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
