The Artima Developer Community
Sponsored Link

The C++ Source
In the Spirit of C
Opinion
by Greg Colvin
June 21, 2004

<<  Page 3 of 3

Advertisement

The Simple Oak

Because the circle of chaos was closing in on the realm, the hero went to the troll and, forcibly subduing him, demanded to know the secret of drawing order out of chaos. The troll replied, Give me your left eye and I'll tell you. Because the hero loved his threatened people so much, he did not hesitate. He gouged out his own left eye and gave it to the troll, who then said, The secret of order over chaos is: Watch with both eyes. (John Gardner)

Java was created in the heat of battle during the Great Browser Wars. The business requirement was for a portable language whose compiled code could be run safely on unsecured Web browsers, and whose syntax and semantics were familiar enough to be easily learned by existing programmers. The hitherto obscure Oak project, originally targeted at devices like set-top boxes for cable TV, was rechristened Java and the substantial resources of Sun Microsystems were applied to bringing Java to market. As it happened, Java had little impact as a Web browser plug-in, but found a welcome audience among engineers creating server-side systems for Web-based commerce, and among educators seeking cheap, simple tools for teaching object-oriented programming.

The design of Java emphasizes Proverbs 3 and 4, sacrificing power and speed for safety and simplicity. Not only is Java completely type-safe, there is no undefined behavior at all. This safety is enforced both by the language and by the virtual machine, so that not even malicious object code can damage the host machine. In light of this, Java has done a remarkable job of providing an expressive language that is more than adequate for most programming tasks. The exception is code which needs full control of the hardware or which must make the most efficient possible use of machine resources, including the Java virtual machine itself. Such code must still be written in a lower level language like C++, C, or assembly.

Does this admirable degree of safety mean that the programmer need not be trusted? After all, Java's automatic memory management and lack of pointer arithmetic mean that stray and dangling pointers are impossible. In a word, No, but here are three examples.

First, depending on the situation, automatic memory management can actually make it more difficult to control the memory requirements of a program. Probably the most frequent bug report against our Java implementation is that the garbage collector is leaking. In almost every case these reports are false—it is the Java code itself that is holding onto unneeded objects. And fixing the problems of unnecessary object retention can lead to performance problems, as expensive objects get recreated as needed rather than retained in memory. So various caching strategies are used to prevent the premature destruction of valuable objects, leading to such system classes as WeakReference, SoftReference, PhantomReference, ReferenceQueue, and WeakHashMap.

Second, the lack of stack-allocated objects can make it more difficult to manage resources other than memory. For instance, my first Java program rapidly ran out of file descriptors:

void scanFile(String name, Filter filter) {
   File file = new File(name);
   filter.scan(file);
}

Embarrassingly obvious, of course, but embarrassingly common as well. I soon learned to use finally blocks for lack of destructors.

Third, although undefined behavior is impossible in Java, deadlock and livelock are shamefully easy. Rather than provide deadlock-free language mechanisms for concurrent execution, Java provides only low-level synchronization primitives, leaving it to the programmer to manage contention. Even a simple monitor facility such as provided in Per Brinch Hansen's Concurrent Pascal would have been an improvement, and the thirty years since Hansen's work have seen considerable progress in safe approaches to program concurrency. But for whatever reason Java ignored this work.

The first two examples argue that it is a myth that managing the life cycle of objects is intrinsically easier in Java than in C++. And if anything Java threads are more difficult to use correctly than Unix processes. Despite these caveats, Java has proved a successful tool. It has delivered, to a surprising extent, on its promise of safe, portable programs.

Be careful what you wish for (Anonymous)

Java, as a completely new language, was able to make a much cleaner break from C than C++ could. Even so, it bought greater simplicity at a cost in power and speed that C++ cannot afford to pay. Is there is some hope that C++ can become simpler?

I believe our biggest loss in the Fall from the Grace of B was the simplicity of typeless programming. The loss was necessary, and for C the loss was manageable, but for C++ complexity has become a daunting obstacle. Much of that complexity is in support of generic programming, where advanced practitioners have pushed the original template syntax far beyond it's original purpose. Paradoxically, it may be template semantics that point the way towards a radical simplification of syntax.

The power of generic programming comes from the ability of the compiler to deduce types in context. At the limit, that ability could eliminate the need to declare types. For example, to write a version of GCD that is agnostic as to the types of its arguments we currently write something like

template<typename T>
T gcd(T m,T n){
   while( m > 0 ) {
      if( n > m )
         swap(m,n);
      m = m - n;
   }
   return n;
}
which doesn't look too bad, but gets rapidly worse as the number of types increases, and is nearly impossible if the result type depends on more than one argument type. So I would like to see the template syntax made optional, and let the compiler do the work:
gcd(m,n){
   while( m > 0 ) {
      if( n > m )
         swap(m,n);
      m = m - n;
   }
   return n;
}
Very clean and simple, just like B. And yet very safe, as the compiler can ensure that all the deduced types are compatible. [Editor's note: This is essentially how templates work in the D language!]

It is tempting here to continue on with more "wish list" items, but that's the topic of my next article.

Acknowledgement

Thanks to Angelika Langer for her comments on the first draft of this article.

Talk Back!

Discuss this article in the Articles Forum topic, In The Spirit of C.

About the Author

Dr. Greg Colvin has been hacking happily since 1972. He is a contributing member of the ANSI/ISO C++ standards committee (and chief designer of auto_ptr) and a Principal Member of Technical Staff with the Java Products Group at Oracle Corporation. In his spare time he plays apocalyptic electric blues guitar in his Colorado, USA home studio.

<<  Page 3 of 3


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us