Ratzenberger on the Manual Arts

When someone I’ve just met asks me what I do for a living and I say I work in software, I sometimes hear wistful responses like, "Oh, that’s cool and it must be a lot of fun. All I do is…" followed by carpentry, plumbing, teaching, farming, or another occupation or trade.

To me, that’s backwards: Any of those things is at least as important, and at least as worthy of respect and appreciation, as what we technologists do. I usually respond by saying so, and adding: "When the power goes out, I’m pretty much useless; worse still, everything I’ve ever made stops working. What you make still keeps working when the power is out."

I can make a pretty good argument that the non-technology skills are more valuable/applicable, but the more important thing is that all skills are deserving of respect and appreciation. Technology has done wonders, and it’s super fun to be involved in that and to have our advances and skills recognized; after all, software has helped build the tools we use to make other real things, including cars and buildings and spacecraft. But it’s unfortunate when sometimes people who focus too heavily on the so-called "higher technology" skills forget, or devalue, the people and skills that built their house, their couch, and their car. Nearly everyone has skills and personal value worth appreciating.

John Ratzenberger makes a similar point:

"The manual arts have always taken precedence over the fine arts. I realized that there is no exception to that rule. You can’t name a fine art that isn’t dependent on a manual art. Someone’s got to build a guitar before Bruce Springsteen can go to work. Someone had to build a ceiling before Michelangelo could go to work."

We live in a richly technologically enabled society, which we can and should enjoy. But when a natural disaster (or just a programming glitch) strikes, and we’re suddenly without power and Nothing Works Any More, we realize how fragile our comfort infrastructure can be.

A couple of months ago here in the northwest United States and western Canada, we had a windstorm that left 1.5 million people without power. Our house was dark and cold for just three nights; many of our friends were out for a week. It can be startling to find oneself unable to talk to anyone without physically going to them: Our cell phones didn’t work at our house, because many cell towers had no power. Many people were chagrined to discover that their landline telephones didn’t work either, because even though the phone lines were fine, the telephone (or base station for a cordless phone) that most people attach requires separate power. Skype wasn’t an option, needless to say, even while the laptop batteries held out. Thus cut off, we were reduced to walking, or driving where trees didn’t block the roads and if you could find a gas station whose pump was working (those pumps usually need electricity too).

Interestingly, the home phone would have been fine had we been using a retro 1950’s-era handset. We’ve now purchased one to keep around the house for next time. Sometimes simpler is better, even if you can’t see the caller ID.

After the storm, who was it who restored our comfort infrastructure, removed fallen trees, and repaired broken houses and fences? Primarily, it wasn’t us technology nerds — it was the electricians, the carpenters and the plumbers. How we do appreciate them! Fortunately, those people in return also appreciate the software, smartphones, PDAs, and other wonders that our industry produces that help them in their own work and leisure, which makes us feel good about being able to contribute something useful back, and so we all get to live in a mutual admiration society.

Thanks for the thought, John. Oh, and Cheers!

Migrant Technology Workers

Today, Slashdot is running an article on immigration. The discussion thread has some interesting notes (though, alas, the signal-to-noise seems to be noticeably lower than usual when reading at +5 — this seems to be quite a politically charged topic).

It reminds me of something that happened two years ago at the ACCU conference. I was on a panel that seemed innocuous enough, until one of the questions raised was immigration: ‘Is it a Good Thing or a Bad Thing that people come from other countries in order to do high-tech work here?’ I’d been peripherally aware that this debate was going on in America, was interested to observe that it was also going on in the UK, and was quite surprised at what a hot button it had become. There sure was a lot of discussion with fervent opinions in both directions.

I don’t have an opinion either way on the issue, but I just thought I’d share an interesting (I hope) observation about perspective, as someone who is from Canada and now lives and works in the United States and thinks well of both places and the people in them: It’s interesting to me that in America (as in Canada), I have seen concerns like this about immigration and people coming from elsewhere to perform domestic professional jobs. I can understand the feelings behind those concerns. On the other hand, during the 35 years I lived in Canada I saw equally frequent and vocal concerns about emigration and the "brain drain" of professionals leaving Canada for the United States — notably doctors and high-tech folks, but we did lose a lot of actors too. And Bill Shatner. (Just kidding; I like Shatner.)

Isn’t it interesting that when a skilled person moves, some people in the country they’re joining are worried that they’re arriving, and some people in the country that they’re leaving are equally worried that they’re going?

Just a thought. Back on Slashdot, though, my favorite comment was:

"Mr Gates did mention that 640K skilled immigrants ought to be enough for USA."

Maybe till January 18/19, 2038. :-)

Welcome to Silicon Miami: The System-On-a-Chip Evolution

A lot of people seem to have opinions about whether hardware trends are generally moving things on-chip or off-chip. I just saw another discussion about this on Slashdot today. Here’s part of the summary of that article:

"In the near future the Central Processing Unit (CPU) will not be as central anymore. AMD has announced the Torrenza platform that revives the concept op [sic] co-processors. Intel is also taking steps in this direction with the announcement of the CSI. With these technologies in the future we can put special chips (GPU’s, APU’s, etc. etc.) directly on the motherboard in a special socket. Hardware.Info has published a clear introduction to AMD Torrenza and Intel CSI and sneak peaks [sic] into the future of processors."

Sloppy spelling aside (and, sigh, a good example of why not to live on on spell-check alone), is this a real trend?

Of course it is. But the exact reverse trend is also real, and I happen to think the reverse trend is more likely to dominate in the medium term. I’ll briefly explain why, and support why I think the above is highlighting the wrong trend and making the wrong prediction.

Two Trends, Both Repeating Throughout (Computer) History

Those who’ve been watching, or simply using, CPUs for years have probably seen both of the following apposite [NB, this spelling is intentional] trends, sometimes at the same time for different hardware functions:

  • Stuff moves off the CPU. For example, first the graphics are handled by the CPU; then they’re moved off to a separate GPU for better efficiency.
  • Stuff moves onto the CPU. For example, first the FPU is a coprocessor; then it’s moved onto the CPU for better efficiency.

The truth is, the wheel turns. It can turn in different directions at the same time for different parts of the hardware. Just because we’re happening to look at a "move off the chip" moment for one set of components does not a trend make.

Consider why things move on or off the CPU:

  • When the CPU is already pretty busy much of the time and doesn’t have much spare capacity, people start making noises about moving this or that off "for better efficiency," and they’re right.
  • When the CPU is already pretty idle most of the time, or system cost is an issue, people start making the reverse noises "for better efficiency," and they’re right. (Indeed, if you read the Woz interview that I blogged about recently, you’ll notice how he repeatedly emphasizes his wonderful adventures in the art of the latter — namely, doing more with fewer chips. It led directly to the success of the personal computer, years before it would otherwise likely have happened. Thanks, Woz.)

Add to the mix that general-purpose CPUs by definition can’t be as efficient as special-purpose chips, even when they can do comparable work, and we can better appreciate the balanced forces in play and how they can tip one way or another at different times and for different hardware features.

What’s New or Different Now?

So now mix in the current sea change away from ever-faster uniprocessors and toward processors with many, but not as remarkably faster, cores. Will this sway the long-term trend toward on-processor designs or toward co-processor designs?

The first thing that might occur to us is that there’s still a balance of forces. Specifically, we might consider these effects that I mentioned in the Free Lunch paper:

  • On the one hand, this is a force in favor of coprocessors, thus moving work off the CPU. A single core isn’t getting faster the way it used to, and we software folks are gluttons for CPU cycles and are always asking the hardware to do more stuff; after all, we hardly ever remove software features. Therefore for many programs CPU cycles are more dear, so we’ll want to use them for the program’s code as much as we can instead of frittering them away on other work. (This reasoning applies mainly to single-threaded programs and non-scaleable multi-threaded programs, of course.)
  • On the other hand, this is also a force against coprocessors, for moving work onto the CPU. We’re now getting a bunch (and soon many bunches) of cores, not just one. Until software gets its act together and we start seeing more mainstream manycore-exploiting applications, we’re going to be enjoying a minor embarrassment of riches in terms of spare CPU capacity, and presumably we’ll be happy using those otherwise idle cores to do work that expensive secondary chips might otherwise do. At least until we have applications ready to soak up all those cycles.

So are the forces still in balance, as they have ever been? Are we just going see more on-the-chip / off-the-chip cycles?

In part yes, but the above analysis is looking more at symptoms than at causes — the reasons why things are happening. The real point is more fundamental, and at the heart of why the free lunch is over:

  • On the gripping hand, the fundamental reason why we’re getting so many cores on a chip is because CPU designers don’t know what to do with all those transistors. Moore’s Law is still happily handing out a doubling of transistors per chip every 18 months or so (and will keep doing that for probably at least another decade, thank you, despite recurring ‘Moore’s Law is dead!’ discussion threads on popular forums). That’s the main reason why we’re getting multicore parts: About five years ago, commodity CPU designers pretty much finished mining the "make the chip more complex to run single-threaded code faster" path that they had been mining to good effect for 30 years (there will be more gains there, but more incremental than exponential), and so we’re on the road to manycore instead.

But we’re also on the road to doing other things with all those transistors, besides just manycore. After all, manycore isn’t the only, or necessarily the best, use for all those gates. Now, I said "all" deliberately: To be sure you don’t get me wrong, let me emphasize that manycore is a wonderful new world and a great use for many of those transistors and we should be eagerly excited about that; it’s just not the only or best use for all of those transistors.

What Will Dominate Over the Next Decade? More On-CPU Than Off-CPU

It’s no coincidence that companies like AMD are buying companies like ATI. I’m certainly not going out on much of a limb to predict the following:

  • Of course we’ll see some GPUs move on-chip. It’s a great way to soak up transistors and increase bandwidth between the CPU and GPU. Knowing how long CPU design/production pipelines are, don’t expect to see this in earnest for about 3-5 years. But do expect to see it.
  • Of course we’ll see some NICs move on-chip. It’s a great way to soak up transistors and increase bandwidth between the CPU and NIC.
  • Of course we’ll see some [crypto, security checking, etc., and probably waffle-toasting, and shirt ironing] work move on-chip.

Think "system on a chip" (SoC). By the way, I’m not claiming to make any earth-shattering observation here. All of this is based on public information and/or fairly obvious inference, and I’m sure it has been pointed out by others. Much of it already appears on various CPU vendors’ official roadmaps.

There are just too many transistors available, and located too conveniently close to the CPU cores, to not want to take advantage of them. Just think of it in real estate terms: It’s all about "location, location, location." And when you have a low-rent location (those transistors are keep getting cheaper) in prime beachfront property (on-chip), of course there’ll be a mad rush to buy up the property and a construction boom to build high-rises on the beachfront (think silicon Miami) until the property values reach supply-demand equilibrium again (we get to balanced SoC chips that evenly spend those enormous transistor budgets, the same way we’ve already reached balanced traditional systems). It’s a bit like predicting that rain will fall downward. And it doesn’t really matter whether we think skyscrapers on the beach are aesthetically pleasing or not.

Yes, the on-chip/off-chip wheel will definitely keep turning. Don’t quote this five years from now and say it was wrong by pointing at some new coprocessor where some work moved off-chip; of course that will happen too. And so will the reverse. That both of those trends will continue isn’t really news, at least not to anyone who’s been working with computers for the past couple of decades. It’s just part of the normal let’s-build-a-balanced-system design cycle as software demands evolve and different hardware parts progress at different speeds.

The news lies in the balance between the trends: The one by far most likely to dominate over the next decade will be for now-separate parts to move onto the CPU, not away from it. Pundit commentary notwithstanding, the real estate is just too cheap. Miami, here we come.

Rico Mariani Interviewed on Behind the Code

Rico Mariani is a performance guru at Microsoft and a wonderful person. After a number of years on the Visual C++ team since 1.0, he went to MSN and then to CLR land where he now beats the "measure! don’t ship bad performance! measure!" drum to much good effect. It’s a pleasure to work with him. Interestingly, Rico is one of the handful of people I polled for "what should I cover" in the new Machine Architecture talk I’m currently writing for the seminar Bjarne and I are doing next month. In the current draft of that talk, I have two slides titled "Mariani’s Methodology (or, Rico’s Rules)" — I’m sure he’ll be mortified at the capitals.

Rico has just been interviewed on Channel 9. Recommended viewing. It’s sprinkled throughout with everything from useful career advice (whether you’re just starting out or looking for a next project), to interesting insights into early Visual C++ and Web product development, to how to ship at high performance and high quality in any language. Rico’s blog is also a great resource — and don’t get hung up when he talks mostly about .NET managed code, because the principles generalize to performance in any language and on any system.

How do friends congratulate the man? The pictures tell the story. Good on you, Rico!

On a sad note: One of the five people previously interviewed on the Behind the Code series is Technical Fellow and Turing Award winner Jim Gray. Jim is still missing after disappearing in the Pacific on January 28. Widely known and loved, he is greatly missed. Our thoughts are with Jim’s family.

ISO C++0x: Complete Public Review Draft In October 2007?

You might say that it looks like "x might not be hex."

I’m happy to report that work on "C++0x", the much-anticipated Version 2.0 of the ISO C++ standard, has dramatically picked up steam over the past few months. The ISO C++ committee has now published the first partial draft of C++0x (for what "partial" means and what’s still missing, see below), and plans to publish a complete public draft before the end of 2007.

In this article I’ll give a quick history of the C++ standard and the current expected timeline. I’ll also summarize (drum roll please) which major features the committee decided to put in C++0x and the features that didn’t make the cut. In the coming months, I’ll go into more detail about these major features as they gel.

From C++98 until now: The story so far

It’s hard to believe it’s been nearly a decade since my first "C++ State of the Union" article appeared in C++ Report. That article, which I wrote on the way home from the July 1997 C++ standards meeting, anticipated correctly that the committee would manage to work through their large bug backlog and vote out a final Draft International Standard at the November 1997 meeting. That they did, to much cheering and fanfare and even a press conference from the main committee room, despite some last-minute excitement involving auto_ptr. ISO took its usual 6-12 months to process red tape, and the first edition of ISO Standard C++ was published in 1998 (aka C++98).

After 1997, the committee deliberately slowed down so as to give the compilers time to catch up to the many innovations in the standard. We’ve been meeting only two (not three) times a year, and from 1998-2003 we limited ourselves to just processing defect reports (bug fixes and requests for clarification) and no new features, to keep the standard stable. In 2002, we finally produced "service pack 1" of the C++ standard, which was published in 2003 (aka C++03).

Then the gates reopened and "C++0x" got underway. New features have been under serious development since 2003-4, and the committee has long had a target of publishing the next C++ standard by the end of the decade; that’s why it has been called "C++0x". (If that schedule fails, we can always make the awkward joke that it’s still C++0x, only x is a hexadecimal number, ha ha. But we’d rather finish on time.)

About C++0x

ISO C++ timeline proposals, October 2006

C++0x target timeline

At the most recent ISO C++ meeting, in October 2006, we considered two main timeline options. They are pictured at right, in a copy of a slide I showed during that meeting to spur discussion. In the first option, we actually publish in 2009 and legitimately get to be called "C++09". In the second, we finish the document in 2009, but because ISO takes most of a year to approve and publish a standard, it would end up as "C++10" (or, one could uncomfortably imagine, "C++0a").

The committee wrung its collective hands, and decided to put in overtime to make the first path happen. Working backward, the dates that need to be hit are:

  • 2009: Publish "ISO/IEC 14883(2009): Programming Language C++"
  • October 2008 ISO C++ meeting: Complete the final text of C++0x and vote it out for balloting, having crossed all the t’s and dotted all the i’s, and in particular having addressed all public comments received during the public review period.
  • October 2007 ISO C++ meeting: Complete the first complete draft of C++0x and vote it out for public review and comments.

Given the work that remains, this means meeting more frequently than we’ve been doing for the past decade. For 2007, the committee agreed to let me put it back on a three-full-meetings schedule, and so for the first time since 1997 we’re having a July meeting. On top of that, subgroups have been organizing additional smaller meetings in between on specific topics, such as concepts. I’ll summarize the meeting schedule at the end of this article.

What’s in C++0x

You can get a very good feel for the contents of C++0x by looking at the first partial draft mentioned above. That draft contains the bulk of the extensions the committee pulled in from the first C++ Standard Library Extensions Technical Report (TR1). It does not, however, contain text for all major features yet, and has placeholders for the major features that I’ll summarize in this section.

Barring a disaster, here are the following additional major features not yet in the above partial draft that will be in C++0x. Every bullet heading links to a good "read this first" paper about the feature, and for some I’ve included additional links.

Concepts [N2081]

From that paper:

"Concepts introduce a type system for templates that makes templates easier to use and easier to write. By checking the requirements that templates place on their parameters prior to template instantiation, concepts can eliminate the spectacularly poor error messages produced by today’s template libraries, making them easier to use. … At the core of concepts is the idea of separate type checking for templates. Template declarations are augmented with a set of constraints (requirements): if the definition of the template typechecks against these requirements, and a use of a template meets these requirements, then the template should not fail to instantiate."

Imagine, if you will, an error message like ‘sorry, YourType isn’t a BidirectionalIterator’ instead of three pages of arcane messages about what templates couldn’t be instantiated. Among other things, concepts will let us write the standard’s own container and iterator requirements in code, rather than as English "cookbooks" of programming conventions.

The concepts proposal is coauthored by Bjarne Stroustrup and Doug Gregor. You can already start trying them out: There is a ConceptGCC proof-of-concept implementation that covers most of the proposal. For more details about how concepts can be applied to the C++ standard library, see also papers N2082, N2083, N2084, and N2085.

Garbage collection [N2129]

A C++0x compiler must provide garbage collection, which the programmer can use on request; "don’t GC this region of code" is still the default. This "opt-in" model leaves existing programs’ semantics unchanged, while providing real GC support for
programs that want it. It is also intended to enable garbage collection for objects allocated and manipulated by most legacy libraries, which both makes it much easier to convert existing code to a garbage-collected environment and helps "repair" legacy code with deficient memory management. Of course, any C++98/03/0x compiler is already free to garbage-collect the whole C++ heap, and a number of current implementations do that; but they aren’t required to do so, and this change would require GC to be available in a way that programmers can use and rely on. This work has been primarily driven by Hans Boehm and Mike Spertus. You can find a detailed paper here: N2128.

Memory model for concurrency [N2138]

As I wrote in "The Free Lunch Is Over", chip designers and compiler writers "are under so much pressure to deliver ever-faster CPUs that they’ll risk changing the meaning of your program, and possibly break it, in order to make it run faster." This only gets worse in the presence of multiple cores and processors.

A memory model is probably of the lowest-level treaty between programmers and would-be optimizers, and fundamental for any higher-level concurrency work. Quoting from my memory model paper: "A memory model describes (a) how memory reads and writes may be executed by a processor relative to their program order, and (b) how writes by one processor may become visible to other processors. Both aspects affect the valid optimizations that can be performed by compilers, physical processors, and caches, and therefore a key role of the memory model is to define the tradeoff between programmability (stronger guarantees for programmers) and performance (greater flexibility for reordering program memory operations)." This work is being driven primary by Hans Boehm, Clark Nelson, and myself.

Concurrency libraries [N2094]

The committee will likely release the concurrency libraries in two parts, both of which are likely to be released at about the same time.

  • In C++0x itself: Support at the level of basic threads and locks, as well as atomic operations for lock-free coding, and related features like thread local storage.
  • In the second C++ Standard Library Extensions Technical Report (aka Library TR2): More advanced extensions including futures and upgradable locks, so that we can gain experience with them before considering them for the standard itself post-C++0x. This follows the same path the committee took with the first set of library extensions, including shard_ptr and the hash-based containers: Those were first put into a separate TR (TR1), completed in 2004, and then based on experience most TR1 features were voted into the standard itself in April 2006 so that they are now part of the current partial draft of C++0x. The TR2 features are planned to be on a similar path, but for now are being released as a separate specification and not part of C++0x.

For more information and snapshots of current draft proposals still under discussion and development, see: N1907, N1966N2047, and N2090.

What’s not in C++0x

The following major features were cut from C++0x because they require more work and would delay the next standard. Once C++0x is done, the committee may pick them up again.

Modules [N2073]

It’s definitely desirable to have a module system for C++ to package libraries and their implementations, and to provide an alternative to C++’s current build model based on textual source file inclusion. Reliance the current source file inclusion model poses technical difficulties for large C++ programs, notably: (a) long build times for large projects; and (b) difficulty of managing dependencies between interfaces and implementations. The current work has been spearheaded primarily by Daveed Vandevoorde (of EDG fame). The committee still intends to do work on this, but it’s now planned as a separate Technical Report on Modules after C++0x is complete rather than as part of the C++ standard.

Dynamic libraries [N1496]

Although C++ programmers routinely use shared libraries in C++ today, the C++ standard doesn’t specify their semantics in a portable way. Indeed, there are some fundamental semantic differences between some popular approaches, such as between Windows static and dynamic libraries and Linux shared libraries. Note that C++’s broad cross-platform support, and the existence of many existing approaches on those different platforms, makes it more difficult to specify portable library semantics than in languages like Java that started fresh with their own (then-new) run-time environment. Several committee members, notably Pete Becker, have done work to try to reconcile the existing approaches in a standard way that implementers could broadly support, but this effort will not be ready in time for C++0x.

Next Steps

Here’s the current list of 2007 meetings, with the "extra" meetings and milestones bolded:

  • Jan 22-24, Batavia, IL, USA: Ad-hoc subgroup meeting on library working group issue cleanup.
  • Feb 22-23, Mountain View, CA, USA: Ad-hoc subgroup meeting on concepts.
  • Apr 15-20, Oxford, UK: Full WG21/J16 spring meeting.
  • Jul 15-20, Toronto, Canada: Full WG21/J16 extra meeting.
  • Sep 29 – Oct 6, Kona, HI, USA: Full WG21/J16 fall meeting. (Extended to Saturday.)
    Goal: Vote out the first complete public review draft of C++0x on Oct 6.

The extra meetings exist specifically to reach the goal of having that full draft before the end of this year. We’ll know as we get closer how well the working paper is coming together.

Regardless of when the first public review draft is published, don’t expect it to be the final text: The draft is to get a round of public comments, and we know there will be issues to refine and tweak over the following year. But that first complete public draft will contain standardese for all major C++0x features in near-final form, which is quite a milestone (and quite a mouthful). It will give us the first real and concrete look at the shape of C++0x.

Over the coming months I’ll be posting additional articles about specific features in the new standard, including some of the cool new features mentioned above. Stay tuned.

Wozniak on Apple

Here’s a wonderful interview with The Other Steve (Wozniak) on the start of Apple. It’s part of a new book called Founders At Work, full of similar interviews with all sorts of well-known founders of companies/products from Adobe and Lotus to TiVo and Ruby on Rails. (I don’t have any commercial interest in the book; I just heard about it via the blogosphere.)

Fair warning: It’s a long interview. But it’s fascinating. Here’s a small excerpt that resonates strongly with me in our highly complexified world of deeply layered and arbitrarily composed software, where programmers are all too often insulated from knowing the true cost of something as simple as a library call:

Livingston: What is the key to excellence for an engineer?

Wozniak: You have to be very diligent. You have to check every little detail. You have to be so careful that you haven’t left something out. You have to think harder and deeper than you normally would. It’s hard with today’s large, huge programs.

I was partly hardware and partly software, but, I’ll tell you, I wrote an awful lot of software by hand (I still have the copies that are handwritten) and all of that went into the Apple II. Every byte that went into the Apple II, it had so many different mathematical routines, graphics routines, computer languages, emulators of other machines, ways to slip your code in and out of an emulation mode. It had all these kinds of things and not one bug ever found. Not one bug in the hardware, not one bug in the software. And you just can’t find a product like that nowadays. But, you see, I had it so intense in my head, and the reason for that was largely because it was part of me. Everything in there had to be so important to me. This computer was me. And everything had to be as perfect as could be made. And I had a lot going against me because I didn’t have a computer to compile my code, my software.

Questions About Exception Specifications

In the past few days, I’ve had several people independently send me email to ask related questions about exception specifications. That must be reason enough to echo some answers here.

Background

For background, here are two places where I’ve written about exception specifications:

I’ve taken the liberty of pasting the entire latter reference at the bottom of this post. Enjoy!

Now on to Question the First…

Q1: How can you know you’ve caught everything if you don’t use exception specifications?

Andrew Skypeck asked:

In CCS#75 you suggest that one ought not provide an exception specifications with functions. Without them, how can a user of the function be certain they have caught all possible exceptions without inspecting the code they are calling? This is often not possible for API users that have header files only.

Two thoughts:

First, the way to catch everything is to catch(…), and that always works. You seem to be wanting to use exception specifications as documentation (which is fine), and so you can get the same ability by writing the exception specification as a comment. Note that even if you try to write them all as actual code, you can’t do it in general — notably you can’t do it for templates, because if a template can be instantiated with any type, you generally can’t know in advance what it might throw.

Second, the caller of a function doesn’t always need to catch all possible exceptions; it should only catch the exceptions that it knows how to handle (or translate). Exception safety is not just about making sure that the code that knows how to detect an error throws, and that the code that knows how to handle the error catches; rather, in practice exception safety is largely about making sure the code in between stays out of the way, including that it doesn’t catch and absorb exceptions. For more about this aspect of exception safety, start with these Items in C++ Coding Standards, and follow the references at the end of each Item to dig into the details that interest you:

  • 70. Distinguish between errors and non-errors.
  • 71. Design and write error-safe code.
  • 72. Prefer to use exceptions to report errors.
  • 74. Report, handle, and translate errors appropriately.

Which brings us to Question the Second:

Q2: Why not statically enforce exception specifications?

Bob Rossi asked, while kindly citing the above article:

I would like to know what the possibilities are of C++0x enforcing the exception specifications like Java does. Here is a good article describing why exception specifications acting the way they do are currently bad, http://www.gotw.ca/publications/mill22.htm

I must not fully understand the situation. What is wrong with the compiler time checks that Java does to enforce the exception specifications? I find this feature extremely useful as a developer!

The short answer is that nobody knows how to fix exception specifications in any language, because the dynamic enforcement C++ chose has only different (not greater or fewer) problems than the static enforcement Java chose.

If you’re interested in reading more about this, try googling for newsgroup postings, http://groups.google.com/groups?q=sutter+exception+specifications. The following is taken from the second hit, which I wrote last fall:

Essentially, exception specifications are a wonderful idea in basic principle, but no one really knows how to design them.

There are two major approaches, and both have serious problems. Java chose static enforcement (at compile time, as suggested above), and C++ chose dynamic enforcement. Interestingly, I see Java people ask "why not enforce these dynamically?" about as often as I see C++ people ask "why not enforce these statically?"

Briefly:

When you go down the Java path, people love exception specifications until they find themselves all too often encouraged, or even forced, to add throws Exception, which immediately renders the exception specification entirely meaningless. (Example: Imagine writing a Java generic that manipulates an arbitrary type T…)

When you go down the C++ path, people love exception specifications until they discover that violating one means invoking terminate, which is almost never what you want.

So why did C++ do exception specifications the way it did, with dynamic enforcement via terminate? And why did Java do it the other way? In both cases, it seemed like a good idea that avoided some set of known problems, and you can’t always know the new problems you incur instead until you gain experience with multiple releases of large code bases, which means over time.

The future of exception specifications?

Bob responded by asking why we don’t just fix exception specifications, or remove them entirely until something better comes along. Those are good questions.

Taking the latter part first: As tempting as it may be, one can’t just rip out a language feature because one decides it isn’t working out quite right. The primary reason is that there are people using the feature, and breaking existing legal code is, well, rude.

What about fixing exception specifications? That would be nice, and I think nearly everyone I know is willing to consider changing them, but only if: (a) there is a well-understood replacement (there isn’t today), and (b) there was a good way to deal with migration from existing code which may rely on the existing feature.

Deliberate change with a strong dose of backward compatibility is always the key. This one needs more deliberation, at least for now, and isn’t expected to change in C++0x.

Epilogue: C++CS Item 75

I’m sure Addison-Wesley won’t mind overmuch if I paste one Item here in its entirety. It has been slightly reformatted for the web.

75. Avoid exception specifications.

Summary

Take exception to these specifications: Don’t write exception specifications on your functions unless you’re forced to (because other code you can’t change has already introduced them; see Exceptions).

Discussion

In brief, don’t bother with exception specifications. Even experts don’t bother. The main problems with exception specifications are that they’re only “sort of” part of the type system, they don’t do what most people think, and you almost always don’t want what they actually do.

Exception specifications aren’t part of a function’s type, except when they are. They form a shadow type system whereby writing an exception specification is variously:

  • Illegal: In a typedef for a pointer to function.
  • Allowed: In the identical code without the typedef.
  • Required: In the declaration of a virtual function that overrides a base class virtual function that has an exception specification.
  • Implicit and automatic: In the declaration of the constructors, assignment operators, and destructors when they are implicitly generated by the compiler.

A common but nevertheless incorrect belief is that exception specifications statically guarantee that functions will throw only listed exceptions (possibly none), and enable compiler optimizations based on that knowledge.

In fact, exception specifications actually do something slightly but fundamentally different: They cause the compiler to inject additional run-time overhead in the form of implicit try/catch blocks around the function body to enforce via run-time checking that the function does in fact emit only listed exceptions (possibly none), unless the compiler can statically prove that the exception specification can never be violated in which case it is free to optimize the checking away. And exception specifications can both enable and prevent further compiler optimizations (besides the inherent overhead already described); for example, some compilers refuse to inline functions that have exception specifications.

Worst of all, however, is that exception specifications are a blunt instrument: When violated, by default they immediately terminate your program. You can register an unexpected_handler, but it’s highly unlikely to help you much because you get exactly one global handler and the only way the handler could avoid immediately calling terminate would be to rethrow an exception that is permissible—but because you have only one handler for your whole application, it’s hard to see how it could do useful recovery or usefully know what exceptions might be legal without trivializing exception specifications altogether (e.g., following the discipline of having all exception specifications allow some general UnknownException eliminates any advantage that having an exception specification might have had in the first place).

You generally can’t write useful exception specifications for function templates anyway, because you generally can’t tell what exceptions the types they operate on might throw.

Paying a performance overhead in exchange for enforcements that are nearly always useless because they are fatal if they ever fire is an excellent example of a premature pessimization (see Item 9).

These is no easy fix for the problems described in this Item. In particular, the problems are not easily solved by switching to static checking. People often suggest switching from dynamically checked exception specifications to statically checked ones, as provided in Java and other languages. In short, that just trades one set of problems for another; users of languages with statically checked exception specifications seem to equally often suggest switching to dynamically checked ones.

Exceptions

If you have to override a base class virtual function that already has an exception spec­ifi­ca­tion (e.g., ahem, std::exception::what), and you don’t have the ability to change the class to remove the exception specifications (or to convince the class’s main­tainer to remove them), you will have to write a compatible exception specification on your overriding function, and you should prefer to make it no less restrictive than the base version so as to minimize the frequency with which it might be violated:

// in a class written by someone else,
// the author used an exception specification,
// and if you can’t get him to remove it…

class Base { // …
virtual f() throw( X, Y, Z );
};

// … then in your own class your override
// must have a compatible (and preferably
// the identical) exception specification
class MyDerived : public Base { // …
  virtual f() throw( X, Y, Z );
};

[BoostLRG]’s experience is that a throws-nothing exception specification (i.e., throw()) on a non-inline function “may have some benefit with some compilers.” Not a stunning endorsement from one of the most highly regarded and expertly designed C++ library projects in the world.

References [see the C++CS online bibliography for reference details and other links]

[BoostLRG] – [Stroustrup00] §14.1, §14.6 – [Sutter04] §13

“Why Are You Doing What You’re Doing?”

For nearly a decade, I’ve had a plaque bearing that question on my desk.

I think the question is valuable because it goes directly to motive. It’s also a deliciously contextual question — it means something different every minute, depending on what you’re up to. Here are a few scattered examples:

  • "Why am I doing this job?" Is it because someone, or society, told me that this was "success" (see last week’s Friday Thought)? Because it’s a way to make ends meet? Because I really enjoy it? Because this is a fun and cohesive team? Because I’m too tired to look for another job? Because I don’t think I could make it at a job I’d actually like to do?
  • "Why am I writing the code this way?" Is it because someone told me to, even though I don’t completely understand the reason? Because it’s the right way? Because I’m under time pressure and plan to fix it later? Because it’s a short cut and I don’t care about this product? Because I haven’t looked in Knuth’s classic The Art of Computer Programming to see if there’s already a known better structure or algorithm? Because I’m tired or distracted? Or because of something else?
  • "Why did I fail to show appreciation for a friend’s help?" Is it because I failed to realize how much they helped me, and at what cost to themselves? Because I was too absorbed/tired/stressed/distracted with just my own troubles? Because I care, but repeatedly failed to show it when it mattered? Because perhaps I actually do need to care more about other people and actively take an interest in them? Because of some combination of the above, and/or possibly more reasons?
  • "Why am I driving to the store?" Is it because that’s what everyone does? Because it’s what I’ve always done? Because I don’t have time to walk or bike (and if so, why not)? Because the groceries are too heavy/bulky to carry back? Because I haven’t thought of riding a bike in years?
  • Etc.

Nobody’s perfect. I’ve wrestled with these and other questions, as I’m sure you do too, and try to improve a little every day and every year.

Being intentional is more than just about programming. We can get there if we keep trying.

Channel 9 Interview: Software Composability and the Future of Languages

Last week, Anders Hejlsberg, Erik Meijer, Brian Beckman and I recorded an interview/chat that covered a range of topics related to programming and languages.

The video is now available online. Here’s the summary pasted from the Channel 9 site:

Software Composability and the Future of Languages
Anders Hejlsberg, Herb Sutter, Erik Meijer, Brian Beckman

How will imperative programming languages evolve to suit the needs of developers in the age of Concurrency and Composability? What role can programming languages play in enabling true composability? What are the implications of LINQ on the future of managed (CLS-based) and unmanaged(C++) languages? How will our imperative languages (static) become more functional (dynamic) in nature while preserving their static "experience" for developers?

Answers to these questions and much more are to be found in this interview with some of Microsoft’s leading language designers and programming thought leaders: Anders Hejlsberg, Technical Fellow and Chief Architect of C#, Herb Sutter, Architect in the C++ language design group, Erik Meijer, Architect in both VB.Net and C# language design and programming language guru, and Brian Beckman, physicist and programming language architect working on VB.Net.

This is a great conversation with some of the industry’s most influential programming language designers. Tune in. You may be surprised by what you learn…

Apologies in advance if the video doesn’t work for some combination of platforms and browsers.