Re: Response to ROOT criticism?

From: Philippe Canal <>
Date: Wed, 09 Aug 2006 23:04:31 -0500

> In a sense, if CINT would interpret `dynamic_cast' as it's supposed to
> (and not as a `static_cast') then one could get the same type safety
> from doing
> Root> Bar* bar = dynamic_cast<Foo*>(gDirectory->Get("foo"));

Note that this is already implemented using the syntax:

     Bar *bar;

which does the exact same thing as your previous code (in addition work whether the user class derives from TObject or not)

> `gDirectory' could then be a macro (like gPad).

We have basically decided to go in this direction (actually most likely there would be one 'current' directory per thread) However this is only the tip of the thread-safety iceberg. We are currently working out how to make more of the I/O operations 'thread-safe' (and which I/O operations)

> That said, I'd like to put in a caveat. Smart pointers are very good at
> ensuring referential integrity, but it's not fool proof.

In addition, we have the additional responsibility of making it backward compatible. This usually means that we have to leave the straight pointer interface (or a very close equivalent) available. Then you end up in the situation where the user can chose between typing:

       TSmartPtr<Bar> bar = gDirectory->Get("foo"); or

        Bar* bar = gDirectory->Get("foo");
and often some user will chose the 2nd one (faster to type) and often this set of users is the same that really need to use the first one. More importantly, in my guess :), one of the most used coding style is to copy/paste/extend somebody else's code that works. To make matter 'worse', that somebody else might be a user that actually read and understood the user's guide chapter on ownership of object and knew her code would work without the smart pointer .... All that to say that I see many reasons why the smart pointer solution is not as helpful as one might think.

That said :) this has been requested often enough that we may end up implementing something like a reference counted pointer .... To support smart pointer in the interpreter we could either (semi?)-automatically generate the dictionary for the needed refcounted pointer (as mentioned by Christian) or somehow 'emulate' them in the interpreter or simply interpret the code of the template itself or some other combinations :) ... As always if there is a volunteer to help out in the implementation and testing, this would speed up the development :)


-----Original Message-----
From: [] On Behalf Of Christian Holm Christensen
Sent: Wednesday, August 09, 2006 7:31 PM To: Andy Buckley
Cc: Rene Brun;
Subject: *SPAM* Re: [ROOT] Response to ROOT criticism?

Hi all,

[just a few cents - I have no intention in joining a flame war or feed the troll :)]

On Fri, 2006-08-04 at 19:10 +0100, Andy Buckley wrote:
> Rene Brun wrote:
> > Andy Buckley wrote:

> >> Memory management / object ownership
> >> ------------------------------------
> > There are many reasons why (by default) we
> > take the object ownership. As always when taking this kind of
> > decisions, you have pros and cons. I imagine the reactions from very
> > unhappy users if we were forcing them to manage objects like
> > histogram. And I repeat, you can manage these objects yourself
> I didn't know that the object ownership stuff could be forced off. And
> yes, it's a design decision. Admittedly, it would be a moot problem if
> ROOT used the Boost ( or other shared pointers,
> e.g. .

It would actually be nice if every time you made a dictionary for a class, say Foo, you'd also create an instance of TSmartPtr<T> and a dictionary for it. TSmartPtr<T> could then be a reference counted smart pointer. Doing that, things like `TDirectory::Get' could return such a smart pointer to the user, and she's have the type-safety right there. Of course, proper `operator=' would have to be defined, to avoid bad access.

Suppose the key `foo' points to an object of class Foo (deriving only from TObject say). Suppose someone did

   Root> TSmartPtr<Bar> bar = gDirectory->Get("foo")

This operation should fail, and `bar' should be invalid, in the sense that

   Root> std::cout << (!bar ? "bad" : "great!") << std::endl;

should print `bad'. This can be done thanks to ROOT's knowledge of what the key `foo' points to (and would never work without that knowledge).

In a sense, if CINT would interpret `dynamic_cast' as it's supposed to (and not as a `static_cast') then one could get the same type safety from doing

   Root> Bar* bar = dynamic_cast<Foo*>(gDirectory->Get("foo"));

However, the TSmartPtr<T> approach could also make sure that the object is not freed from memory until the last reference to it dies, or could even flag to others that the reference is no longer valid (more tricky). The cool thing is, that this would also work across the interpreter/binary code divide.

It's a relatively cheap thing to implement, and doesn't necessarily break backward compatibility.

That said, I'd like to put in a caveat. Smart pointers are very good at ensuring referential integrity, but it's not fool proof. One has to be consistent in using them all over the place for the reference counting to make sense. No silver bullet, as Andy puts it.

The Boost smart pointers are way too bloated for a processing heavy framework like ROOT.

Interestingly, Objectivity sort of used smart pointers for queries, storage specs, and so on. However, Objectivity's implementation was cluttered due to the lack of proper template support in some compilers.

> Incidentally, I'm not the only one who finds current ROOT memory
> management awkward: it wasn't even one of my criticisms until a bunch of
> other people contacted me to say it was their number one complaint!

Please, citing un-named sources must be frowned upon - and truly not very scientific. Put up the names, numbers, contexts, etc. and your argument will have much more weight. If not, it's hear-say at best.

> > Yes, the penalty is
> > a global object gDirectory. I know the problems with that
> > (multithreading), but I believe that the pros outweighs the cons.

Erhm. If you had `TDirectory::Instance()' pointing to the `current directory' it could be more thread-safe. `gDirectory' could then be a macro (like gPad).

> That's a shame, because I think it's an interesting point: templates are
> dynamic through polymorphism, i.e. good class hierarchy design. I'd be
> interested to know of a circumstance where they aren't flexible and
> generic enough, as much for personal information as anything else.

What I think Rene is talking about, is that two separate instances of a class template are not related in any way. That is, if you have class template Foo<T> and instances Foo<int> and Foo<float> they are not polymorphic. The only way to make them sort-of polymorphic, is to have a base class for the class template (which is what I think Andy is talking about), or to implement the class template to only accept types that derive from a particular base class

   class FooBase { ... };
   template <typename T> class Foo : public FooBase { ... }    

   Foo<int> f1;
   FooBase& r1 = f1; // OK
   Foo<float>* p1 = &f1; // Error.

   class BarObj { enum { isBar = 1 }; ... };

   template <int A> struct Check { SomeThingThatMakesCompileFail; };
   template <> struct Check<1>  {};
   template <typename T> class Bar 
     typedef Check<T::isBar> BarCheck;  
     operator () T() { return T(*this); }

   struct B1 : public BarObj { ... };
   struct B2 : public BarObj { ... };

   Bar<B1> b1;
   BarObj* p1 = &b1; // OK
   Bar<Foo> b2; // Fail
   Bar<B2> b3;
   p1 = &b3; // OK

To those who really want to understand what templates can and cannot do, I suggest you read Andrei Alexandrescu's book 'Modern C++ Design' from Addison Wesley's `C++ In-Depth' series.   

Templates are cool, but not always suitable for the problem at hand.

> How is this an improvement over having external
> "HistogramPainter" classes?

I think Andy is thinking about Aida here.

> "this is only a question of religion, mainly raised by those not
> understanding the advantages of a coherent framework": condemning
> "religious" views and then presenting one :) I have no problem with a
> coherent framework, I just want to be able to use one other than ROOT.

And which one would that be then? I'd be interested in hearing about other projects that have the same functionality as ROOT (and I don't just mean histograms and plotting - I want DB acces, remote file access, 3D geometry, persistence, and so on, all in a _coherent_ framework). Honestly, I'd like to know.

> > I did not see in the discussions any worries/concerns about the ROOT
> > persistency mechanism. I believe that this is a big success and
> > probably the main reason why ROOT is so successful.

It's funny to see how the same (often not well-founded) criticism is echoed again and again. If I had a cent for each time I heard almost the same opinion ... well surfixe to say that I'd wealthy. The problem is, that many times people don't really know the underlying arguments and just echo the conclusion, or they have a very bad misconception about the whole business - probably because they couldn't be bothered to read a manual (who ever said it's `manly' not to read manuals - what a moron).

Please, make sure you have all the information, that you understand the technical difficulties, that you perhaps have tried to make a rival implementation before you go shooting off unfounded criticism.

> and, I'm afraid, many private emails to me that I'm not going to
> reproduce.

Tsk. What ever happened to the good scientific practise of citing or not tell at all.

> And my experience in the HepMC/CLHEP discussion recently was
> that many senior computing people in LCG and the experiments regard ROOT
> persistency (and in particular the fact that it doesn't separate
> transient and persistent objects) as deeply problematic.

Try to work with something like Objectivity and you'll see that the issue is far more complex than you'd think.

Incidentally, does anyone have a pointer to the cited LCG Persistency Blueprint?

> --- that came naturally as
> a result of learning how OO *should* be done. But let's avoid the
> personal stuff, yes?

Well, show us how it `*should* be done.' then! Seriously. Let's discuss the technical aspects from a technical point of view - that amounts to design documents, working prototypes (w/source code), and similar. Enough of this `ROOT sucks, but I cannot show you how it `*should* be done.'' - and please, OpenScientist is unfortunately mostly vaporware.

On Mon, 2006-08-07 at 13:12 +0100, Andy Buckley wrote:
> Rene Brun wrote:
> > Andy Buckley wrote:
> > It would be good if templates could be defined at run time.
> Yes, it would but no-one else in the world needs it to do so, because
> no-one else tries to interpret C++.

Not true. Take a look at

A google search could probably produce more results.

> Because that's not what it's
> designed for. And this is exactly why I hardly ever use ROOT

Your problem.

There was a time when ROOT was the under-dog. Now it's more like the top-dog :) However, we should all do well to remember that things _can_ (and does) grow out of the roots (no pun intended), and we'd better keep our eyes open for the next `ROOT'. So from this true-believer, the best of luck to people that want to have a go at a newer and better physics analysis framework (whoops, almost wrote Workstation there :).


 ___  |  Christian Holm Christensen 
  |_| |  -------------------------------------------------------------
    | |  Address: Sankt Hansgade 23, 1. th.  Phone:  (+45) 35 35 96 91
     _|           DK-2200 Copenhagen N       Cell:   (+45) 24 61 85 91
    _|            Denmark                    Office: (+45) 353  25 404
 ____|   Email:               Web:
 | |
Received on Thu Aug 10 2006 - 06:16:52 MEST

This archive was generated by hypermail 2.2.0 : Mon Jan 01 2007 - 16:32:00 MET