Re: [boost] Review of a safer memory management approach for

Fernando and Jeffrey, A few responses ...
------------------------------
Message: 6 Date: Fri, 04 Jun 2010 00:14:25 -0300 From: Fernando Cacciola <fernando.cacciola@gmail.com> To: boost@lists.boost.org Subject: Re: [boost] Review of a safer memory management approach for C++? Message-ID: <hu9r1a$57q$1@dough.gmane.org> Content-Type: text/plain; charset=UTF-8; format=flowed
...
For instance, it's been so long since I last wrote a virtual function that recently, I made the silly mistake of forgetting that, in a derived class, an overrided function doesn't have to specify the virtual keyword ;)
[Bartlett, Roscoe A] High warning levels (i.e. with GCC) catch most such mistakes that the language proper allows to go through. BTW, are you gravitating to stack-based programming because of the memory management problems or because of problems of change propagation of shared mutable objects? These are almost 100% unrelated issues in my opinion. Is the C++ boost community really ready to throw away OO programming? That just seems crazy to me.
------------------------------
Message: 9 Date: Thu, 03 Jun 2010 21:12:52 -0700 From: "Jeffrey Lee Hellrung, Jr." <jhellrung@ucla.edu> To: boost@lists.boost.org Subject: Re: [boost] FW: Boost Digest, Vol 2929, Issue 4 Message-ID: <4C087D44.1080909@ucla.edu> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
...
As for sharing of objects, it is critical for many types of software in the Computational Science and Engineering (CSE) domain. You have to share large objects in order to cut down on runtime and storage overhead. As one example, consider the Petra object model with the Trilinos packages Epetra and Tpetra (http://trilinos.sandia.gov/). In the Petra object model, you have objects with significant storage overhead like Maps and Graphs that are shared between many different objects like Vectors, MultiVectors, and Matrices. Yes, you could create deep copies of Maps and Graphs but that would waste a large amount of storage. The bottom line is that by sharing large objects like Maps and Graphs instead of making large numbers of copies, we can fit and solve much larger simulation problems on a computer than we could otherwise. You could template and statically allocate everything and you will never get around the fundamental need to share the data contained in large objects in these types of applications.
Note, however, that Maps in Epetra/Tpetra are shared as const immutable objects. That means that no-one can change a Map after it is first created. Therefore, all of the problems with unexpected updates goes away (as you mention above). However, the shared Maps must go away when they are not needed anymore and that is what the Teuchos::RCP class makes easy and robust. Under the covers, Tpetra uses Tpetra::ArrayRCP for similar purposes and much more. The situation with Graphs is different and issues of change propagation of shared objects are still present in some cases.
Come to think of it, most of the object sharing that used in the CSE software that I use and write mostly just share const immutable objects so problems of change propagation mostly goes away. However, there are some important use cases where all of the clients are not holding RCPs to const objects and the problem of change propagation remains. Again, to save in significant runtime and storage overhead, we can't just create deep copies of all of these objects. Templating and purely stack-based programs are not going to solve that problem.
The Teuchos MM approach, I believe, largely solves the memory management problems with dynamic memory allocation and object sharing while still yielding very high performance and mostly eliminating undefined behavior associated with the incorrect usage of memory. The most significant contribution of the Teuchos MM approach is the presents of Teuchos::Ptr and Teuchos::ArrayView and how they interact with the other classes.
I don't see how shared object *ownership* is necessary in this example... :/ I don't think Dave was arguing that holding large objects by reference, or even dynamically allocating objects (large or not), is necessarily complex or "bad"...
Or did I miss something?
[Bartlett, Roscoe A] Have you read the key sections in the Teuchos MM approach in http://www.cs.sandia.gov/~rabartl/TeuchosMemoryManagementSAND.pdf or are you just responding to the list emails? You should *never* hold an object by reference as a class data-member (except perhaps in very well encapsulated very low-level code). That is what leads to undefined behavior with dangling references. Early versions of Epetra did just that and it blew up in people's faces. Consider writing a factory method such as: Epetra_CrsMatrix* createMyMatrix(....) { Epetra_Map rowMap(...); Epetra_Map colMap(...); ... Epetra_CrsGraph graph(rowMap, colMap); ... Epetra_CrsMatrix *matrix = new Epetra_CrsMatrix(graph); ... return matrix; } In early Versions of Epetra, maps and graphs were held and references and the above factory function returned an Epetra_CrsMatrix object with now deleted map and graph objects. Later, Epetra was refactored to make Epetra_Map and Epetra_Graph handle classes with internal reference-counted handle/body implementation objects. This fixed the problem but it create lots of new problems including that now copying graphs silently went from deep copy to shallow copy (which broke some code in some rare cases). The new Tpetra package has gone the down the road of making shared ownership explicit by exposing RCP-wrapped objects making factory functions similar to the above safe and obvious in behavior. It is working very well. Cheers, - Ross

On 4 June 2010 13:33, Bartlett, Roscoe A <rabartl@sandia.gov> wrote:
Is the C++ boost community really ready to throw away OO programming? That just seems crazy to me.
What do you lose by throwing away OO? Objects for the sake of having objects? RAII is a better OO than OO ever was, since it has a justification for using objects. Here's a list of things that OO is sometimes defined to be: <http://www.paulgraham.com/reesoo.html>. We keep, at least as much as "OO C++" has them, 1, 2, 3, 5, 6, and 8. For 4 we have boost::any. We provide 7 through type erasure layers over 3 (using "OO" features). We drop 9, but it's a restriction, not a feature. So what's the big deal?

Bartlett, Roscoe A wrote:
For instance, it's been so long since I last wrote a virtual function that recently, I made the silly mistake of forgetting that, in a derived class, an overrided function doesn't have to specify the virtual keyword ;)
[Bartlett, Roscoe A]
High warning levels (i.e. with GCC) catch most such mistakes that the language proper allows to go through.
BTW, are you gravitating to stack-based programming because of the memory management problems or because of problems of change propagation of shared mutable objects? These are almost 100% unrelated issues in my opinion.
Is the C++ boost community really ready to throw away OO programming? That just seems crazy to me.
Since virtual functions and templates are oil and water it shouldn't be surprising that the boost community doesn't use many virtual functions. Even so there are so many bad things about virtual functions and inheritance (let alone multiple inheritance) and so little benefit in most cases that it is a bizarre accident of academic language development and instruction that OO is such a dominant design style. From what I can tell most people come up with an OO design by default without making a design decision or thinking about their design options. Usually an OO design is not the best way to go, inheritance and especially dynamic polymorphism are not needed or helpful and the resulting implementation is overcomplicated code bloat layerd on top of some absurdly simple C style programming and some use of the stl. There are so many classes written that should be POD structs and so many classes written that should be just a function that people have some how come to a conclusion that this is normal and all to the good. People are writing classes and virtual functions without knowing why. If you write an application or library that you want to compile once and release as a binary with header files but no source files and then let people change the behavior of *your* code at link type (especially dynamic linkage) then virtual functions are a way to do that and people use them for that. That's not the kind of thing most boost libraries need or want, it is something for collaboration of closed source software shops who don't trust each other and large unwieldy applications that have a build system more complicated than the space shuttle. Boost doesn't resemble either case. Regards, Luke

Le 04/06/2010 19:13, Simonson, Lucanus J wrote:
Even so there are so many bad things about virtual functions and inheritance (let alone multiple inheritance) and so little benefit in most cases that it is a bizarre accident of academic language development and instruction that OO is such a dominant design style.
I believe that in the pure form of OO, all functions are multimethods. This basically makes it work like overloading, except it's dynamically typed.

...and you can't detect ambiguities and other overload failures at compile-time. [sent from tiny mobile device] On Jun 7, 2010, at 5:34 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org
wrote:
I believe that in the pure form of OO, all functions are multimethods. This basically makes it work like overloading, except it's dynamically typed.

Hi Bartlett,
High warning levels (i.e. with GCC) catch most such mistakes that the language proper allows to go through.
Right. I actually wasn't even actually writting code (so no compilation). I was just sketching up an excercise were I intended to show a case of hidding of a virtual, but forgot the change the signature! And this was caught by a reviewer.
BTW, are you gravitating to stack-based programming
I'm not sure if you are calling stack-based what we called value-semantics by mistake, or are you effectively considering automatic storage. I'm gravitating to value-semantics. Then even dynamically-allocated objects by usage of handle/body idioms. But let's say that you are just misusing the term stack.
because of the memory management problems or because of problems of change propagation of shared mutable objects?
The latter. Honestly. I'm at a total lost about what problem are you trying to solve that requires such a big framework. I never needed anything beyond shared_ptr (ok well, perhaps a *couple* of weak_ptrs), and I'm very well aware of its limitations (like circular references). Is just that my designs naturally don't do any of that, for reason totally unrelated to memory managment or that fact that I happen to use simple reference counting. So that's a non-existent problem for me.
These are almost 100% unrelated issues in my opinion.
Indeed.
Is the C++ boost community really ready to throw away OO programming?
I can't speak for the boost community, but I don't think anyone is doing that. There are many forms of OO, and idioms within. What I am particularly ready to throw away is the excess weight in an object graph, which IMO isn't a treat of OOD&A itself but just a property of a particular design. And one such way to cut the excess is to rely less on shared objects and dynamic-polymorphism which in C++ just happens to be based on a structural coupling between classes (unlike the case of other OO languages) -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

Fernando Cacciola skrev:
Hi Bartlett,
But let's say that you are just misusing the term stack.
because of the memory management problems or because of problems of change propagation of shared mutable objects?
The latter.
It is also worth noticing that encapsulation, one of the hall-marks of OO programming, is much easier to code in a language with value-semantices. -Thorsten

Le 04/06/2010 20:56, Fernando Cacciola wrote:
Honestly. I'm at a total lost about what problem are you trying to solve that requires such a big framework. I never needed anything beyond shared_ptr (ok well, perhaps a *couple* of weak_ptrs), and I'm very well aware of its limitations (like circular references). Is just that my designs naturally don't do any of that, for reason totally unrelated to memory managment or that fact that I happen to use simple reference counting. So that's a non-existent problem for me.
It could be argued than a cycle within your ownership responsibility graph (which should really be a hierarchy) is a serious design issue to begin with. One reason is that you cannot have a determinate order of resource cleanup in that case. Yet a lot of people keep working on providing an automatic resource management mechanism that deals with cycles without even wondering if it's not the cycles themselves that are the problem. Of course, in some languages, it's necessary, as there is no way to distinguish between an owning pointer and a mere reference. But does C++ really need this?

On Fri, Jun 4, 2010 at 1:33 PM, Bartlett, Roscoe A <rabartl@sandia.gov> wrote:
Is the C++ boost community really ready to throw away OO programming? That just seems crazy to me.
The other day, when pointing out some design problems, someone asked me if I was "just anti-OO". I hadn't thought about it before they asked, but I guess often my answer is yes. In 20+ years of coding, only rarely did OO actually work out as 'advertised'. Actually, I should specifically say polymorphism (since I find other OO things like encapsulation useful quite often). Runtime polymorphism is great in those few cases where that is what the problem actually asks for, but it turns out to not actually happen as often as it seems people expected it to happen. Tony
participants (8)
-
Bartlett, Roscoe A
-
David Abrahams
-
Fernando Cacciola
-
Gottlob Frege
-
Mathias Gaunard
-
Scott McMurray
-
Simonson, Lucanus J
-
Thorsten Ottosen