eyt*
Oct 28, 2004

Extending C++ and Java...

For the past week, I have been at OOPSLA, and I have been rather busy collecting all kinds of information that I will eventually talk about here, but I thought that I would start slowly discussing the conference.

Herb Sutter presented yesterday a talk entitled, “Concrete Languages on Virtual Platforms,” and the talk was slightly differently than what I had in mind. What I had imagined was more of a discussion of why we use virtual platforms and targeting language features on the platform, but alas the discussion was about the coercion of C++ onto the .NET platform for Version 2.0.

As you are aware, C++ has, for the sake of simplification, two types of variable allocation methods, viz. stack variables and heap-allocated variables. Stack variables are constructed when introduced, and are destroyed at the end of the scope of where they are introduced, whereas heap-allocated variables are constructed by calling new and are destroyed by calling delete.

The situation is, however, that the CLI platform uses garbage collection. Porting C++ onto the CLI means introducing garbage collection into the language. Stroustrup has always said that garbage collection would be added to the language, however, the approach that was chosen is not standard, and will result in code specific to the .NET platform, such as follows:

MyClass ^t = gcnew MyClass()

As you see, there is a new keyword, gcnew, and this is assigned to a garbage collected pointer, denoted by the caret (^, or the hat), and following this, you can use the pointer as a standard pointer. The other change is with the destructor of the class, whereby the finalizer method is now !MyClass(). You can read this for yourself over at MSDN. Herb does, however, point out that this is a standard language extension, but I agree with Kevlin Henney that this is like saying that C++ is a standard language extension of C.

In addition to bringing up some bad memories from Pascal, I am not convinced that this is the best way to implement garbage collection within the C++ language, but this is not what I really wanted to talk about today, so I will leave this topic for another day. But while discussing all of this, one of the topics that Herb focused on is, what he finds, the horrors of finalization. In Herb's mind, we need to distinguish between object destruction and freeing memory, and garbage collection is only focused on the latter, but today, this is not really true. As an example, in your finalizer, an object could be resurrected by simply assigning the this pointer into a static variable. As another example, per se that you have a set of objects that depend on each other in a circular fashion. In this case, the garbage collector must then choose one of those objects to destroy first. This means that when the object calls the finalizer, it cannot access other objects, as these objects may have been destroyed prior to this finalizer. Because of these reasons (and more), Herb insists that garbage collected languages separate the concept of object destruction and freeing memory.

The only facility, however, where I feel that this makes a difference is with patterns, such as the Scope Locking Pattern [POSA2] and other scope-related patterns, which are important in languages like C++. As an illustrative example, the following code acquires a lock and then calls doSomeOperation():

void MyClass::myFunction()
{
  LockGuard lock( objectLock );
  doSomeOperation();
}

In the above pattern, the lock constructor acquires a lock, and the destructor releases the lock, and this is a very safe way of implementing multithreaded applications, but in languages like Java and C#, the above Pattern is not utilized, because there are no destructors, and, if they run at all, finalizers may be ran much later than you expect.

For the sake of argument, let us ignore the fact that Java has the synchronize keyword (which actually Herb's presentation did) and imagine that we are using a set of classes, similar to those discussed here. Now our implementation in Java becomes a little heavier than the above C++ implementation:

void javaMethod() {
  LockGuard lock = new LockGuard( objectLock );
  try {
      doSomeOperation();
  } finally {
      lock.release();
  }
}

When there is more code, the more chance that developers will get it wrong (an another argument against the gcnew and ^). In so saying, Herb also points out that the C# fashion of accomplishing this is via:

void csharpMethod() {
  using ( new LockGuard( objectLock ) ) {
    doSomeOperation();
  }
}

In such a comparison, this looks horrible for Java. In fact, in my first exposure to C#, I mentioned the fact that I really liked the using keyword, and as such, I hoped that this would eventually be brought over the Java.

One very interesting part of attending OOPSLA is that there are many big names in the software industry. In fact, sitting right beside me during the above discussion was Joshua Bloch. Earlier today Joshua was signing copies of his Effective Java book, and having read this book in my early Java days, I approached him and asked him about the types of things that he would change in the book. It turns out that he is presently writing a book on Java Puzzles (I presume something like Herb's Exceptional C++ series) and after this, he will be updating this book, and to remain on topic for once, I will just say that there are some very interesting additions to this book coming soon.

Following the book discussion, I asked Joshua about what he thought about adding the using keyword to Java, and it turns out that he was presenting some ideas at The Java Platform: Tiger and Beyond workshop, and essentially what he says is that the using keyword only does something when exiting the scope, and does not do something when entering the scope. In addition to not adding a new keyword to the Java language, his idea is to essentially introduce a new interface which we will call, for lack of a better name, Doable, which is defined as follows:

public interface Doable {
  void begin();
  void end();
}

From this interface, the idea is that the developer would use it via the following:

do ( new MyDoableClass() ) {
  doSomething();
}

And underneath the hood, some equivalent structure as the original Java implementation above would be created and that would call the interface methods also. This is a very exciting idea, but now that I think about it, I think that perhaps the begin() method would be rarely used. Specifically, if you consider the above implementation, I am constructing a new concrete interface, therefore most of what could be placed in the begin() method would usually be placed in the constructor. This is not to say that you will never have a class passed in that will already exist that may benefit from this begin() method, but I would imagine that this would not be the norm, and in the rare case that a method like begin() would be required, the method could be explicitly called prior to the doSomething() from above. More specifically, I see the more popular uses of this construct being more localized references, such as manipulation of I/O, Sockets, SQL, etc., which currently require a close() method to be called in a finally section. I cannot think of any case where the begin() would be useful off the top of my head, but I am sure there are some cases; I just am not sure how necessary this is.

Nevertheless, I look forward to seeing something like the above implemented in a future Java version, in addition to some of the other proposals that I have heard, including switch statements on Class and Strings and adding a const-like feature to Java, such as is implemented in javari, of which I may describe at a later time.

Filed In

Navigation

eyt*