For some the motivation behind this question may be interesting. The
motivating question is : do C++ programmers / software designers perceive
any advantages to explicitly deallocating memory over implicitly
deallocating memory when the last reference is used?
--
Christopher Diggins
yet another language designer
http://www.heron-language.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
I should say: It depends. There are many kinds of smart pointers. As an
example std::auto_ptr is one, and it is *not* a reference counting one. So
one should really make a difrerence between smart pointers providing shared
ownership, and the ones providing RAII.
In our project there are not too many smart pointer uses (due to the
structure). One of the major uses is due to undeterministic lifetime, the
"last one switches the lights off" effect. The rest is simple RAII, because
there is no need for shared ownership. But our case is possibly special,
due to the framework we use and the rules it has to simplify things.
As for the general question, I think the shared ownership is a valid
possibilty. As long as "someone" refers to an object, it should be there.
But in case of a code using exceptions the "RAII reason" is equally
important. And they can be important at the same time. So I honestly
believe that it is impossible to answer this question. There are different
kinds of smart pointers and their use is different as well. And whatever
use is done, at that time it is important.
I have a friend, who prefers to do deallocation by hand. Eh, he did. Until
I have managed to make his code leak like a bucket used for target practice
at an Uzi factory. :-)
For me the question does not make a perfect sense, because there are many
kinds of smart pointers and many different uses. Equally important on its
own right.
--
Attila aka WW
This communication is confidential and intended solely for the addressee(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you believe this message has been sent to you in error, please notify the sender by replying to this transmission and delete the message without disclosing it. Thank you.
E-mail including attachments is susceptible to data corruption, interruption, unauthorized amendment, tampering and viruses, and we only send and receive e-mails on the basis that we are not liable for any such corruption, interception, amendment, tampering or viruses or any consequences thereof.
The short answer: to avoid mistakes.
I would say that the exact answer depends very much on what flavour of smart
pointer you're using. If it's something like a boost::shared_ptr, then the
intention is obviously to manage shared memory blocks through reference
counting.
On the other hand, something like std::auto_ptr is obviously designed with
the opposite effect in mind: to ensure that only one party "owns" a block of
memory.
> bugs resulting from memory access errors or primarily to permit lazy
> deallocation designs (i.e. designs that rely on non-determined non-fixed
> non-explicit deallocation of memory)? Obviously both are advantages, but I
> want to know if programmers are finding that lazy deallocation is one of
the
> major uses of smart pointers.
"Lazy" deallocation designs? I would never apply that particular adjective.
Think of it this way: by using the RAII pattern we ensure that the path of
least resistance is also the correct path. But there is far more to it than
coping with forgetful programmers who forget to delete. What if an
exception is thrown in the middle of a method, before the delete can take
effect? You'd have to account for every single possible exception, and wrap
it in a try block, with the delete in the catch block. I don't know about
you, but even if I could think of every eventuality, I wouldn't want to have
to. Plus all those try/catch constructs would make the code unreadable.
"Sane" or "reasonable" would be more appropriate than "lazy" ;-).
There's another important consideration here that I think you're missing.
Using RAII proxies like auto_ptr have an important design effect: *they
increase the level of specialization of code*. Consider:
1)
DbConnection dbcon(connectionPool);
DbResult r = dbcon.query("select * from users;");
for_each(r.begin(), r.end(), notifyUser());
2)
DbConnection* dbcon = connectionPool->acquire();
DbResult *r = dbcon->query("select * from users;");
for_each(r->begin(), r->end(), notifyUser());
delete r;
connectionPool->release(dbcon);
Which would you rather have? Clearly (1) expresses the logic of the program
more concisely than (2). The delete and release() are necessary, but not
interesting. By moving them to a proxy class, we've achieved a greater
level of clarity. Plus our code is now exception safe.
So in short, smart_ptr<> is the first step on a long road. Welcome to the
new C++.
Regards
David Turner
P.S. One quick gripe: you said "designs that rely on non-determined
non-fixed non-explicit deallocation of memory". While the last adjective
surely applies, the first two certainly do not.
You probably need to be clearer about what you want to resolve.
> Is it primarily to reduce
> bugs resulting from memory access errors or primarily to permit lazy
> deallocation designs (i.e. designs that rely on non-determined non-fixed
> non-explicit deallocation of memory)?
I've probably implemented more smart pointers than the average C++
programmer, but I've never implemented one to address either of these
motivations.
I have implemented smart pointers:
o As part of a persistance mechanism.
o To provide implicit access locks.
o To encapsulate decisions on object lifetime.
o To replace "boiler plate" code supporting implementation hiding
techniques.
o To encapsulate the navigation over a collection.
> Obviously both are advantages, but I
> want to know if programmers are finding that lazy deallocation is one of the
> major uses of smart pointers.
Programmers that want that in C++ are more likely to use a garbage
collector.
> For some the motivation behind this question may be interesting. The
> motivating question is : do C++ programmers / software designers perceive
> any advantages to explicitly deallocating memory over implicitly
> deallocating memory when the last reference is used?
I doubt it: while there are many advantages to executing the
destructor of objects that own resources when the last reference dies
there is no particular advantage to reclaiming memory at this time.
(Of course, there should be a guarantee that the memory will won't
leak.)
--
Alan Griffiths
http://www.octopull.demon.co.uk/
I believe there are two major categories of smart pointers: those
design to manage ownership a dynamically allocated object and those
that do other things.
The first category is meant to reduce memory deallocation errors,
rather than access ones. In general I would say that lazy deallocation
is considered a liability rather than an asset by C++ programmers, as
it makes destructors useless. Moreover, if lazy deallocation is
desired, a garbage collector would probably be a better solution.
> For some the motivation behind this question may be interesting. The
> motivating question is : do C++ programmers / software designers perceive
> any advantages to explicitly deallocating memory over implicitly
> deallocating memory when the last reference is used?
I'm sure that programmers that make a living out of memory analizer
tools perceive a definite advantage to explicit deallocation :-)
Cheers,
Nicola Musatti
> What I am trying to answer is, what the most prominent motivation for
> implenting and using smart pointers in C++ is. Is it primarily to reduce
> bugs resulting from memory access errors or primarily to permit lazy
> deallocation designs (i.e. designs that rely on non-determined non-fixed
> non-explicit deallocation of memory)? Obviously both are advantages, but I
> want to know if programmers are finding that lazy deallocation is one of the
> major uses of smart pointers.
I'm participating in a large software project using smartpointers
extensively, and I think without the smartpointers the project would
have never succeeded.
Using smartpointers just for "reducing memory access errors" is IMHO not
quite appropriate, because this might only hide errors instead of fixing
them (e.g. if some pointer is not updated correctly). OK, you usually
shift access violations into weird runtime (non-)behaviour, but an error
is an error. So I believe the most important reason to use smartpointers
is automatic memory management - keeping an object alive as long as it
is referenced, and also properly releasing it afterwards to avoid memory
leaks. At least in our project the latter task seems almost impossible
without smartpointers (or garbage collection, for that matter, but we
haven't tried that).
> For some the motivation behind this question may be interesting. The
> motivating question is : do C++ programmers / software designers perceive
> any advantages to explicitly deallocating memory over implicitly
> deallocating memory when the last reference is used?
I prefer explicit deallocation for better control over the program (you
know, C++ is about control ;-). But I also think smartpointers *are*
explicit deallocation.
Regards
Paavo
I don't understand your terms so I'll answer the point I think you
are getting at.
I believe all of my smart pointers are used to control memory-only
objects which don't need lifetime modelling. I could use a garbage
collector instead. I don't rely on timely destruction of the
pointed-to objects. They are not file handles or GUI windows or
sockets or anything like that.
I generally use them when the memory management is too complex to do
by hand. This may be because of exceptions, or because of transfers
of ownership, or because the objects are shared.
> For some the motivation behind this question may be interesting. The
> motivating question is : do C++ programmers / software designers
> perceive any advantages to explicitly deallocating memory over
> implicitly deallocating memory when the last reference is used?
Some objects have definite lifetimes which have to be managed, and
it's often good to make that explicit. However, that isn't the same
as saying it is good to link lifetimes with manual deletion. If my
machine had infinite RAM, I doubt I'd delete anything ever.
-- Dave Harris, Nottingham, UK
They make it explicit that deletion will be done somewhere, but the
ordering of the deletion w.r.t. other operations is implicit. With
a smart pointer that provides exclusive ownership it is at least
possible to point to the place in the code where it will be done in
the non-exceptional case - usually after the last statement in a
block. With reference-counted smart pointers this generally becomes
impossible; if it is possible we presumably needn't use reference-
counting. In the presence of concurrency, deletion of reference-
counted objects is not even deterministic.
There is a serious potential problem with reference-counting of
objects that use synchronisation. If the destructor synchronises
then it must be safe to do that at any point that they can be
deleted, i.e. it must not violate the mutex hierarchy. This is a
tough constraint to put on code that isn't explicitly deleting
anything but is merely assigning (smart) pointers. So this type
of object will generally need to be deleted later, either by
explicit deletion or by garbage collection (with finalisation in
a separate thread).
(This problem is described in Hans-J. Boehm's paper
"Destructors, Finalizers and Synchronisation"
<http://www.hpl.hp.com/techreports/2002/HPL-2002-335.pdf>.)
The quality of posts in response to my query have been of superlative
quality and very informative.
The shift of errors from access violations into strange runtime
behaviour
interests me greatly because it is the principal reason why I left
garbage
collection out of my programming language Heron in the first place. I am
pleased to see that others have identified this problem as well. Are you
familiar with any documentation leading to this?
Part of the reason for the inquiry in this newsgroup was to find out
whether
it would be inevitable that programmers require smart pointers even if
they
had well behaved pointers (i.e. no dangling pointers, fewer memory
leaks).
The consensus seems to be that smart pointers definitely have their own
merits especially in "last one out turns off the lights" design
scenarios.
If this leads to programmers implementing their own smart (auto freeing
memory) pointers in Heron, then it should probably be part of the
standard
library and implemented in a very efficient manner.
Thanks again to everyone who has responded!
--
Christopher Diggins
yet another language designer
http://www.heron-language.com
> I believe all of my smart pointers are used to control memory-only
> objects which don't need lifetime modelling. I could use a garbage
> collector instead. I don't rely on timely destruction of the
> pointed-to objects. They are not file handles or GUI windows or
> sockets or anything like that.
I think that's an excellent characterization, at least of the classical
smart pointers. I've also used smart pointers for transaction
management: the pointer makes a copy of the object, for roll-back, or
grabs a lock, etc. In one case, I maintained a number of sets of
pointers to the object, using different fields of the object as the key
in the sets. All non-const access to the objects was through a smart
pointer which removed the object from the sets, so that update of the
key fields was safe, and reinserted it in the destructor.
I've actually found smart pointers more effective at this sort of thing
than for memory management.
> I generally use them when the memory management is too complex to do
> by hand. This may be because of exceptions, or because of transfers of
> ownership, or because the objects are shared.
I would have said the reverse: I generally use memory management smart
pointers when the issue is simple enough for them to work. Once it gets
compilcated, I find that I have to introduce raw pointers, etc., to
break cycles. They are, in fact, a poor mans garbage collection, and
far inferior to real garbage collection (but still far better than doing
everything by hand).
> > For some the motivation behind this question may be
> > interesting. The motivating question is : do C++ programmers /
> > software designers perceive any advantages to explicitly
> > deallocating memory over implicitly deallocating memory when the
> > last reference is used?
> Some objects have definite lifetimes which have to be managed, and
> it's often good to make that explicit. However, that isn't the same
> as saying it is good to link lifetimes with manual deletion. If my
> machine had infinite RAM, I doubt I'd delete anything ever.
Infinite RAM, or garbage collection.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
This is correct, if you factor weak_ptr out of the equation. But the
shared_ptr+weak_ptr combination can be used to turn the classical
Observer (the pointee keeping list of observers to notify on
destruction) inside out, so that the target (whose lifetime is managed
by shared_ptr) no longer needs to know who is observing.
This kind of thing can't be replaced with garbage collection. In a
garbage-collected language we'd use Observer (or put the pointee in a
zombie state) as there is no alternative, but things aren't as
one-dimensional as it might seem.
> This is correct, if you factor weak_ptr out of the equation. But the
> shared_ptr+weak_ptr combination can be used to turn the classical
> Observer (the pointee keeping list of observers to notify on
> destruction) inside out, so that the target (whose lifetime is managed
> by shared_ptr) no longer needs to know who is observing.
>
> This kind of thing can't be replaced with garbage collection.
Why? Practical garbage collectors provide weak pointers.
--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
What is correct? I'm not claiming that all uses of smart pointers
can be replaced by garbage collection. On the contrary, I am making
the point that some cannot; but all /mine/ can. I think the
distinction between those that can and those that cannot is what the
original poster was reaching for in his question.
If you mean that "memory-only objects" is not quite the right
characterisation of those which can, then James Kanze made a similar
point and I agree. There are objects which don't own external
resources but which need timely destruction.
However, this doesn't have much to do with weak_ptr. Garbage
collection can (and should) also provide weak pointers, which work
the same way as weak_ptr. They are notified (or at least nulled)
when the pointed-to object disappears. So we can use the same trick
to get rid of Observer.
The difference is that with garbage collection the pointed-to object
will not "disappear" in a timely way. It will hang around until its
memory is reclaimed for something else. So we can't piggy-back our
life-time management on top of the memory management. We have to
deal with the problem-domain issues (such as a file being closed)
separately from the implementation-domain issues (the file's memory
being reclaimed).
Some people argue this is a good thing: that they are different
levels of abstraction and so best kept separate. (But see below.)
> (or put the pointee in a zombie state)
Indeed. And the absence of such zombie states is a potential benefit
of conflating the levels of abstraction.
At least, it is if we can be sure that the smart pointers are used
consistently, and there is no chance of getting a dangling pointer;
a deleted object is worse than a zombie. This is a traditional
weakness of C/C++ and a tradition strength of GC languages like Java:
the latter enforce the rules and eliminate dangling pointers. But they
do so at the cost of allowing zombies.
However... I have classes which use the "Resource Acquisition
is Initialisation" idiom to give themselves strong class invariants
without zombie states, but I think they are all allocated on the
stack rather than with heap, so they don't need smart pointers. I
guess they just happen not to need polymorphism.
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[...]
> However, this doesn't have much to do with weak_ptr. Garbage
> collection can (and should) also provide weak pointers, which work the
> same way as weak_ptr. They are notified (or at least nulled) when the
> pointed-to object disappears. So we can use the same trick to get rid
> of Observer.
I've got some hesitations about this (which are equally valid for weak
pointers in garbage collection and for those in Boost). At least in my
experience, just setting the pointer to zero when the lifetime of the
object ends is not sufficient. In most cases, some sort of active
notification is necessary, or at least desirable. (This is actually
possible if the garbage collection supports finalization, as the Boehm
collectors do.)
I'm not sure I understand Peter's point concerning the Observer pattern.
Who contains the weak pointer: the observer (to the observed object), or
the observed object (to the observers). In the first case, you probably
need some sort of notification to whoever owns the Observer, so the
Observer can also be deleted, and in the second case, you end up with a
lot of dead references to observers in the observed object. In both
cases, you doubtlessly want to inform the actual object of the demise of
the other, so that the dead references can be removed.
> The difference is that with garbage collection the pointed-to object
> will not "disappear" in a timely way. It will hang around until its
> memory is reclaimed for something else. So we can't piggy-back our
> life-time management on top of the memory management. We have to deal
> with the problem-domain issues (such as a file being closed)
> separately from the implementation-domain issues (the file's memory
> being reclaimed).
> Some people argue this is a good thing: that they are different levels
> of abstraction and so best kept separate. (But see below.)
> > (or put the pointee in a zombie state)
> Indeed. And the absence of such zombie states is a potential benefit
> of conflating the levels of abstraction.
In practice, you have three choices:
- dangling pointers,
- zombies, or
- active notivation.
Garbage collection or boost::share_ptr are identical in this respect.
Weak pointers provide a weak form of active notivation -- the pointer is
set to null, and can be tested on the next access. This is certainly
better than nothing, but it doesn't do much for removing the memory
which the nulled pointer occupies, and it doesn't do anything if the
observer (whoever held the weak pointer) must take some concrete action
on the end of lifetime of the other object.
> At least, it is if we can be sure that the smart pointers are used
> consistently, and there is no chance of getting a dangling pointer; a
> deleted object is worse than a zombie. This is a traditional weakness
> of C/C++ and a tradition strength of GC languages like Java: the
> latter enforce the rules and eliminate dangling pointers. But they do
> so at the cost of allowing zombies.
> However... I have classes which use the "Resource Acquisition is
> Initialisation" idiom to give themselves strong class invariants
> without zombie states, but I think they are all allocated on the stack
> rather than with heap, so they don't need smart pointers. I guess they
> just happen not to need polymorphism.
If the lifetime of the object corresponds to a scope, then some sort of
scoped object is definitly the best solution. Neither garbage
collection nor shared_ptr are the solution for everything.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[...]
> I'm not sure I understand Peter's point concerning the Observer pattern.
> Who contains the weak pointer: the observer (to the observed object), or
> the observed object (to the observers). In the first case, you probably
> need some sort of notification to whoever owns the Observer, so the
> Observer can also be deleted, and in the second case, you end up with a
> lot of dead references to observers in the observed object. In both
> cases, you doubtlessly want to inform the actual object of the demise of
> the other, so that the dead references can be removed.
The shared_ptr+weak_ptr "idiomatic" design is poll-based, instead of
message-based, with the observers holding a weak_ptr to the observed.
It follows naturally from the fact that you can't do anything with a
weak_ptr except obtaining a shared_ptr from it (any other access is
unsafe since a weak_ptr does not guarantee that the object will stay
alive). Expressed via code, this idiomatic access is:
weak_ptr<X> wx;
if( shared_ptr<X> px = wx.lock() )
{
// process *px
}
else
{
// the observed object has been destroyed
}
The upside is that the observed object does not need to know about the
observers, reducing dependencies. The downside is that constant
polling is slower than active notification. In my experience, polling
is often affordable.
As an aside, active notification, if invoked by the garbage collector,
is dangerous for two reasons. First, there is no guarantee that the
observer will be notified in a timely manner, or even at all. Second,
the notification will run in the garbage collector thread; this may
lead to deadlock.
A variation of the second item may also apply to active notification
schemes that aren't collector-based; it's very rare, of course, but
such a bug is also very hard to find. ;-)
(Of course I don't want to imply that shared_ptr+weak_ptr is the
ultimate solution, or something. It has its own fair share of
problems. Just outlining a design possibility.)
> [...]
> > I'm not sure I understand Peter's point concerning the Observer
> > pattern. Who contains the weak pointer: the observer (to the
> > observed object), or the observed object (to the observers). In the
> > first case, you probably need some sort of notification to whoever
> > owns the Observer, so the Observer can also be deleted, and in the
> > second case, you end up with a lot of dead references to observers
> > in the observed object. In both cases, you doubtlessly want to
> > inform the actual object of the demise of the other, so that the
> > dead references can be removed.
> The shared_ptr+weak_ptr "idiomatic" design is poll-based, instead of
> message-based, with the observers holding a weak_ptr to the observed.
I know. I could have written a lot more about all of the trade-offs,
but the size of an news article is limited. The topic could easily fill
a book.
> It follows naturally from the fact that you can't do anything with a
> weak_ptr except obtaining a shared_ptr from it (any other access is
> unsafe since a weak_ptr does not guarantee that the object will stay
> alive). Expressed via code, this idiomatic access is:
> weak_ptr<X> wx;
> if( shared_ptr<X> px = wx.lock() )
> {
> // process *px
> }
> else
> {
> // the observed object has been destroyed
> }
> The upside is that the observed object does not need to know about the
> observers, reducing dependencies. The downside is that constant
> polling is slower than active notification. In my experience, polling
> is often affordable.
OK. I had a different Observer pattern in mind, in which active
notification of changes in the observed object played an important part.
There are, in fact, two aspects involved here. One is the actual
notification (a word with implies an event in my mind) -- if, for
example, someone clicks on a button in a GUI, this should generate an
event which must be treated immediately. I don't think that the Boost
pointers are meant to address this question.
The other is related memory management. If the screen is changed so
that the button is removed, the component representing it should die --
either be deleted (current C++) or become a zombie. The question is,
what happens to any event handlers or observers in this case. There are
three possibilities:
- the event handler becomes irrelevant, and must also die,
- the event handler is only observing this one particular object, or
- the event handler may be observing any number of objects.
In the first case, some additional logic is needed; what will depend on
the circomstances. In the second, using a weak_ptr works very well; you
have a single pointer, which is either valid or not. In the third,
using a weak_ptr only solves half of the issue -- at some point in time,
you should remove the pointer (weak or otherwise) from the collection of
pointers. Still, polling for the removal is probably sufficient.
Note that similar scenarios are often a source of memory leaks even with
full garbage collection. In Swing, for example, there is a class
Action; it is designed to be both an observer and an observee for
various GUI components such as buttons. Which means that both it and
the component maintain pointers to one another. When I dismiss a
window, all of the buttons in it disappear, BUT there is no active
notification. Originally, the Action maintained a pointer to the button
(which prevented its collection), and the button maintained a pointer to
the component which contained it, ad infinitum (which prevented
collection of the entire window hierarchy). The current implemenation
uses Java weak pointers in the registration mechanism, which is, IMHO, a
hack -- the correct solution is to notify the button that it is dying,
and for the button to de-enrol from whatever it is observing. (IMHO, of
course. I wouldn't want to accuse the authors of Swing of using an ugly
hack.)
> As an aside, active notification, if invoked by the garbage collector,
> is dangerous for two reasons. First, there is no guarantee that the
> observer will be notified in a timely manner, or even at all. Second,
> the notification will run in the garbage collector thread; this may
> lead to deadlock.
I agree that active notification should NOT, EVER be invoked by the
garbage collector. In fact, all of my hestitations turn around the fact
that with garbage collection, OR with boost::smart_ptr, you need
additional notification logic -- in other words, you (may) have to deal
with zombies. In this context, weak_ptr is a sort of an intermediate
state. If you can deal with zombies, it isn't really needed -- when you
find a zombie, you zap the pointer, then do whatever you have to do free
up the memory which holds the pointer. Again, a polling approach, but
then, that's what zombies imply anyway.
Anyway, my personal preference is for active notification, even with, or
perhaps especially with, real garbage collection. From experience,
zapping the pointer is only rarely the only action you have to apply.
> A variation of the second item may also apply to active notification
> schemes that aren't collector-based; it's very rare, of course, but
> such a bug is also very hard to find. ;-)
Generally speaking, dynamic designs are harder to debug than static
ones:-). The boost::shared_ptr/weak_ptr helps for certain types of
problems. My experience (which is far from universal) suggests that
active notification handles more cases, more flexibly, and leads to less
errors. On the other hand, I don't know how to create a truely generic
active notivation scheme -- if the boost::shared_ptr/weak_ptr work, it's
sure that they require a lot less coding on the part of the application
programmer. (There are exceptions, of course. In at least one
application, we needed a fairly generic active notification for external
notifications, and it was trivial to use it for internal notification as
well.)
> (Of course I don't want to imply that shared_ptr+weak_ptr is the
> ultimate solution, or something. It has its own fair share of
> problems. Just outlining a design possibility.)
I understand. My current position hasn't changed: we really need
(optional) garbage collection in the language. Not that that would
provide an ultimate solution either -- while it would solve a lot of
frequently occuring problems, it would also introduce a few new problems
of its own.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
No, that's the domain of Boost.Function and Boost.Signals. But I have
to admit that Signals and weak_ptr do not integrate at an acceptable
level, not yet. A good solution would immediately auto-disconnect
&X::f from the signal when it detects that the weak_ptr to that X has
been invalidated. The Signals library currently uses its own mechanism
that is notification-based and requires a base class (which is, I
believe, a source of problems with multiple threads).
[...]
> > (Of course I don't want to imply that shared_ptr+weak_ptr is the
> > ultimate solution, or something. It has its own fair share of
> > problems. Just outlining a design possibility.)
>
> I understand. My current position hasn't changed: we really need
> (optional) garbage collection in the language. Not that that would
> provide an ultimate solution either -- while it would solve a lot of
> frequently occuring problems, it would also introduce a few new problems
> of its own.
I'm still very much uncomfortable with the phrase "(optional) garbage
collection". :-)
We have witnessed the idiomatic C++ style change several times. At
first it was very much like what Java is today, 'new' and base classes
everywhere. Then came the templates, and container libraries adapted;
no more single-rooted hierarchies. Then came the STL. Then we got
template (partial) specialization and the compiler became a Turing
machine.
I strongly suspect that in C++ with garbage collection the idiomatic
designs will be radically different. This isn't bad in itself; it's
probably a good thing. But when you add the (optional) in front of
garbage collection, this means that you no longer know whether your
design is good or bad. You need to pick a target audience, and this
means fragmentation.
In my opinion, the presence or absence of garbage collection should be
part of the language specification. Optional garbage collection is
like optional multiple inheritance, optional exception handling,
optional RTTI, optional template partial specialization. :-) Or maybe
even worse, because you get no error or warning at compile time, just
leaks at runtime.
> I'm still very much uncomfortable with the phrase "(optional) garbage
> collection". :-)
> We have witnessed the idiomatic C++ style change several times. At
> first it was very much like what Java is today, 'new' and base classes
> everywhere. Then came the templates, and container libraries adapted;
> no more single-rooted hierarchies. Then came the STL. Then we got
> template (partial) specialization and the compiler became a Turing
> machine.
> I strongly suspect that in C++ with garbage collection the idiomatic
> designs will be radically different.
I don't think so. At least it shouldn't be (IMHO), most of the time.
Just because you have garbage collection available doesn't mean that
objects with value semantics or RAII should be abandonned.
> This isn't bad in itself; it's probably a good thing. But when you add
> the (optional) in front of garbage collection, this means that you no
> longer know whether your design is good or bad. You need to pick a
> target audience, and this means fragmentation.
> In my opinion, the presence or absence of garbage collection should be
> part of the language specification. Optional garbage collection is
> like optional multiple inheritance, optional exception handling,
> optional RTTI, optional template partial specialization. :-) Or maybe
> even worse, because you get no error or warning at compile time, just
> leaks at runtime.
I think you misunderstood my "optional". I didn't mean that it was
optional for the compiler; I meant that it was optional for the
programmer. As much as I favor garbage collection, there are at least a
few cases where you will still want explicit management of dynamic
memory, and you should have the right to do so.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Nope, I have found this out in the hard way ;-( For example, we have
developing some kind of interpreted script language. Recently I
discovered that one can write a procedure in it (in the GUI text
editor) and then delete it immediately, so that the procedure text is
not accessible any more in any way; but nevertheless the procedure can
be called from other scripts and appears to run well ;-) That's what
smartpointers do!
Regards
Paavo
I used the term 'explicit' only in comparison with garbage collectors.
I think I should have said 'deterministic' instead. And note that if
you insist on a strong meaning of determinism, then one doesn't need
to write the program at all because the result is determined
beforehand :-)
In our software, we have logically immutable objects referred to by
smartpointers. And when I have to perform an operation on a 50M
object, then I very much want to know how many references it has; if
I'm the only referrer I can safely change the object in-place,
otherwise I have to make a copy. I guess that in principle gc could
tell me that, too, but in order for this to be effective I believe gc
should itself be based on refcounting(?)
I also know 'deterministically', that when the last smartpointer
disappears, this 50M is released; in case of conservative garbage
collectors, as far as I have understood, the object is not released if
there happens to be a bit pattern coinciding with the object address
somewhere on the heap. Let's say I have another 50M object filled with
random data; the chance for hitting such bit pattern there is
(50M/4)/4G = 0.003125 (for aligned 32-bit pointers). That's not so
small ;-) Or have I misunderstood the gc mechanisms?
Regards
Paavo
If it is required that standard compliant compilers add GC then it will
drive many embedded programmers back to C. The simple fact is that in
environments where available resources are minimal the overhead for GC
that would never be used would be unacceptable. Another significant
issue is in real time applications where an unpredictable GC sweep leads
to any number of problems.
Ken
> >>In my opinion, the presence or absence of garbage collection should
> >>be part of the language specification. Optional garbage collection
> >>is like optional multiple inheritance, optional exception handling,
> >>optional RTTI, optional template partial specialization. :-) Or
> >>maybe even worse, because you get no error or warning at compile
> >>time, just leaks at runtime.
> > I think you misunderstood my "optional". I didn't mean that it was
> > optional for the compiler; I meant that it was optional for the
> > programmer. As much as I favor garbage collection, there are at
> > least a few cases where you will still want explicit management of
> > dynamic memory, and you should have the right to do so.
> If it is required that standard compliant compilers add GC then it
> will drive many embedded programmers back to C. The simple fact is
> that in environments where available resources are minimal the
> overhead for GC that would never be used would be unacceptable.
> Another significant issue is in real time applications where an
> unpredictable GC sweep leads to any number of problems.
As I said, the USE of GC must remain optional. If it costs too much,
then don't use it.
With regards to the second problem, there exist real time garbage
collectors. Mark and sweep isn't the only algorithm. (That said, I'm
sceptical of any use of dynamic memory in a hard real time application.)
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
If you require that unadorned pointers be GCable then you either have to
require that all compilers have a setting to turn GC off completely for
a specific build which will add yet another layer of problems to using
third party binaries or every build will have the overhead of GC whether
it is used in the application or not. I strongly doubt that a compiler
can be made that could optimize away the GC overhead without being
explicitly told to turn GC off.
Ken
I built a pointer libary. It is different from STL smart pointer and
shared pointer. The idea of my design is that it is plain, easy to use
and understand. It is actually the foundation of all of my other work.
It allows two favors of parameter usage. For example,
Var i = 2, j = 3, k;
k = i + j; // k = 5
i = 3; // k = 5 or 6, depending on the parameter setting.
The above writing is easy to understand and easy to use.
Why you ask the user care about the memory? As a user, I don't need to
know how the computer works. I use it to do my work.
Without the pointer libary, this behaviour is difficult to achieve.
Regards
Tony
I think the above would be a recipe for confusion and error. If I have
to track a parameter setting to know what changing i will do to k then I
would not want to be anywhere near such code.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
> >>ka...@gabi-soft.fr wrote:
What overhead? If you don't call malloc, you normally don't get the
code for malloc and for free linked into your application. If you don't
allocate garbage collectable memory, you don't link in the garbage
collector.
Finally, of course, it's probably worth pointing out that malloc/free
are no more predictable (and often less predictable) than GC. If you
have hard real time constraints, normally, you don't use dynamic
memory. If you do, you need a specially designed malloc/free or a
specially designed GC, which gives you a guaranteed upper bound
execution time -- this isn't the case for the malloc/free which come
with most C/C++ compilers. I fail to see the difference between GC and
malloc/free here.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
I don't think James is suggesting anything of the sort. Imagine an
*additional* overload of operator new was provided, say
operator new ( size_t, const std::gc_t & )
which allocated a pointer in garbage collected memory. You'd still be
free to choose whether to use garbage collection or not.
Cheers,
Nicola Musatti
So your suggestion is for special allocation functions for any pointers
that you want GC'ed? This is better than boost::shared_ptr<> how? At
this point you seem to be advocating a different kind of smart pointer
rather than GC.
Ken
The behaviour is needed in many engineering applications. For example,
when a user changes the size of a rectangle, the area of the rectangle
will be updated automatically. In other cases, the behaviour is no
needed. It can be turned off.
So with one source code, you can have multiple behaviours. But avoid
confusion, it is best to have two behaviours only. One is
non-parameteric. The other is parametric.
> So your suggestion is for special allocation functions for any
> pointers that you want GC'ed?
All of the proposals that I am aware of uses two different heaps, one
for garbage collected objects, and another for traditional objects. The
Ellis/Detlefs proposal integrates garbage collection at least partially
into the type system.
> This is better than boost::shared_ptr<> how?
It works. Even in the presence of cycles, and without the programmer
having to think about it.
> At this point you seem to be advocating a different kind of smart
> pointer rather than GC.
No.
You might read the Ellis/Detlefs proposal for starters:
http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-102.html.
Or for more general information, the Garbage Collector FAQ:
http://www.iecc.com/gclist/GC-faq.html.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> I don't think James is suggesting anything of the sort. Imagine an
> *additional* overload of operator new was provided, say
> operator new ( size_t, const std::gc_t & )
> which allocated a pointer in garbage collected memory. You'd still be
> free to choose whether to use garbage collection or not.
That is one possibility.
The most concrete proposal I've seen, the Detlefs/Ellis proposal,
introduces garbage collection partially into the type system: there are
garbage collected types, and non garbage collected types, e.g.:
gc class A {...} ;
typedef gc char B[ 10 ] ;
class C { ... } ;
typedef int D[ 5 ] ;
The expressions new A or new B allocate memory on the garbage collected
heap, the expressions new C or new D on the non-collected heap.
The introduction into the type system isn't pervasive, however: given:
typedef gc int A[ 10 ] ;
typedef int B[ 10 ] ;
I can write code:
int* p1 = new A ;
gc int* p2 = new B ;
(In practice, given that the gc above has no effect on the program, I
imagine that no one would write it. It has no pratical interest, but it
is probably simpler to allow it than to define exactly when it is
forbidden.)
I can also allocate gc objects on the stack, or statically, in which
case, the gc attribute has no effect. (Detlefs/Ellis present it as a
sort of storage class specifier. This is certainly true for its role in
the grammar, like static or extern, it is part of the declaration
specifier, and it applies to the declared symbol(s). On the other hand,
semantically, it works a little differently, and is really a new type of
type modifier.)
I believe that Herb Sutter once considered making it a fundamental part
of the type system, although I don't know whether he was considering a
formal proposal, or just speculating on a possibility. I'm not aware of
any formal proposal which is based on his considerations, however.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
And that is exactly what we can do with classes. My objection is trying
to do it with an iterator. If I see:
rectangle r(1, 4);
std::cout << r.area();
r.width(5);
std::cout << r.area();
I am not at all surprised that the two outputs are different. However:
Var i = 2, j = 3, k;
k = i * j;
std::cout << k;
i = 5;
std::cout << k;
would cause me considerable surprise if the two answers are different
because I have no reason to expect that changing i will change k.
> In other cases, the behaviour is no
>needed. It can be turned off.
If it is never there to start with I do not have to track whether it is
off or on.
>So with one source code, you can have multiple behaviours. But avoid
>confusion, it is best to have two behaviours only. One is
>non-parameteric. The other is parametric.
To avoid confusion it is better that code has a single behaviour that
can be understood by any suitably skillful programmer reading it.
Object specific behaviour should be encapsulated in classes, that is
what they were largely designed to do.
As a student exercise exploring what can be done with iterators is a
good mind expanding exercise but building an entire software structure
on top of such an experimental design seems dangerous to me.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
> The behaviour is needed in many engineering applications. For example,
> when a user changes the size of a rectangle, the area of the rectangle
> will be updated automatically. In other cases, the behaviour is no
> needed. It can be turned off.
It doesn't imply that both behaviors should use the same syntax.
In all languages I know, no matter whether they pass mutable numbers by
value (like Pascal, C, C++ and Perl) or immutable numbers by reference
(like most other languages), if this kind of syntax is valid
k = i + j;
i = 3;
then changing "i" doesn't change "k".
--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
So the area of the rectangle is a computed property. In C++ terms
this means it would be implemented with a member function rather than
member data.
(In some languages the distinction can be hidden from class users. In
C++ there is (I think) no efficiency reason for exposing member data
since it can be selectively exposed through inline member functions,
so properties should be consistently exposed through member functions.
This just leaves the holy war^W^Wquestion of naming.)
> So with one source code, you can have multiple behaviours. But avoid
> confusion, it is best to have two behaviours only. One is
> non-parameteric. The other is parametric.
How does that avoid confusion? It seems to me that it would be better
to make an explicit differentiation, perhaps by introducing lambda
expressions:
k = i + j; // k = 5
i = 3; // k = 5 still
k = lambda() { i + j; } // k = 6 if evaluated
i = 2; // k = 5 if evaluated
ka...@gabi-soft.fr wrote:
> Ken Shaw <non...@your.biz> wrote in message
> news:<nKSYb.46841$hR.10...@bgtnsc05-news.ops.worldnet.att.net>...
>
>
>>So your suggestion is for special allocation functions for any
>>pointers that you want GC'ed?
>
>
> All of the proposals that I am aware of uses two different heaps, one
> for garbage collected objects, and another for traditional objects. The
> Ellis/Detlefs proposal integrates garbage collection at least partially
> into the type system.
>
>
>>This is better than boost::shared_ptr<> how?
>
>
> It works. Even in the presence of cycles, and without the programmer
> having to think about it.
>
>
>>At this point you seem to be advocating a different kind of smart
>>pointer rather than GC.
>
>
> No.
>
> You might read the Ellis/Detlefs proposal for starters:
> http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-102.html.
> Or for more general information, the Garbage Collector FAQ:
> http://www.iecc.com/gclist/GC-faq.html.
>
I generally oppose any solution that seems aimed at making it easier for
lazy and/or poor programmers. This proposal falls in this category.
There are legitimate areas where smart pointers can be helpful but I
don't want some junior programmer adding weird resource management bugs
to my code by being able to use our RAII classes with a GC.
Ken
> >>So your suggestion is for special allocation functions for any
> >>pointers that you want GC'ed?
> > All of the proposals that I am aware of uses two different heaps,
> > one for garbage collected objects, and another for traditional
> > objects. The Ellis/Detlefs proposal integrates garbage collection
> > at least partially into the type system.
> >>This is better than boost::shared_ptr<> how?
> > It works. Even in the presence of cycles, and without the
> > programmer having to think about it.
> >>At this point you seem to be advocating a different kind of smart
> >>pointer rather than GC.
> > No.
> > You might read the Ellis/Detlefs proposal for starters:
> > http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-102.html.
> > Or for more general information, the Garbage Collector FAQ:
> > http://www.iecc.com/gclist/GC-faq.html.
> I generally oppose any solution that seems aimed at making it easier
> for lazy and/or poor programmers.
What about solutions that make it easier for competent professionals to
get their job done? (I'd be all for a solution which would allow poor
programmers to turn out quality work, but I haven't seen one yet.)
Or do you simply do everything in assembler? (Been there. Done that.
Don't what to have to do it again.)
My customers don't pay me to play around. The pay for correctly working
programs. And frankly, I'll use any tool that will increase program
correctness and/or reduce the amount of effort necessary. What with
multithreading and handling asynchronous events in a timely manner, I
don't need additional work.
> This proposal falls in this category. There are legitimate areas
> where smart pointers can be helpful but I don't want some junior
> programmer adding weird resource management bugs to my code by being
> able to use our RAII classes with a GC.
You prefer that he add weird resource management bugs without GC? An
incompetent programmer is incompetent. Code review and such will soon
either improve him, or weed him out. The question is rather how to
improve productivity of the vast majority of competent programmers.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Well you may oppose it but a lot of people don't. The idea is that, want it
or not, in your average team working for your average shop, not all
programmers can be geniuses. There are just too few good programmers and too
much code to write. Besides, democratizing good things from the initiated to
everybody is a tenet of Western thinking :o).
Andrei
You understood correctly. Yet things are not as bad as one might put them.
There are a lot of aspects. One is, most integers in a program are
statistically small; so if the allocator arranges things such that pointers
have big integral values, clashes are reduced. Second, in many systems all
allocated pointers are multiples of four, which reduces chances of clash by
75% for random integers. There are many tricks like that; I remember just
these, but I'm sure gc implementors has more up their sleeves.
Andrei
I have never written an application where I wanted anything closer to GC
than boost::shared_ptr<>. I have written a large amount of java code
where I spent a great deal of time and effort making the GC behave in a
useful manner for the application in question.
> Or do you simply do everything in assembler? (Been there. Done that.
> Don't what to have to do it again.)
>
Actually I do my best to make my life as easy as possible which includes
using a large number of good third party libraries and one of my major
concerns is what impact allowing your kind of optional GC into C++ would
have on my ability to select libraries.
> My customers don't pay me to play around. The pay for correctly working
> programs. And frankly, I'll use any tool that will increase program
> correctness and/or reduce the amount of effort necessary. What with
> multithreading and handling asynchronous events in a timely manner, I
> don't need additional work.
>
In that regard I would just love to see all common UNIX versions fully
support POSIX.
>
>>This proposal falls in this category. There are legitimate areas
>>where smart pointers can be helpful but I don't want some junior
>>programmer adding weird resource management bugs to my code by being
>>able to use our RAII classes with a GC.
>
>
> You prefer that he add weird resource management bugs without GC? An
> incompetent programmer is incompetent. Code review and such will soon
> either improve him, or weed him out. The question is rather how to
> improve productivity of the vast majority of competent programmers.
>
I never said incompetent, I said poor. We try and bring along the below
average programmer who tries hard and learns while getting rid of the
truly incompetent ones. However I have found that these sort of junior
programmers jump on the newest flavor of the month feature in the belief
that it is a silver bullet and I am in favor of reducing the number of
different ways these programmers can introduce subtle bugs into a
project and have found from Java that GC induced bugs are usually not
easily reproducible and not obvious from examining the code that should
be the cause of the failure.
Ken
What if the user has a pointer to that object on the stack, not on the
heap? How does the GC system know not to collect that object if it
only searches the heap?
joshua lehrer
factset research systems
NYSE:FDS
> You understood correctly. Yet things are not as bad as one might put
> them. There are a lot of aspects. One is, most integers in a program
> are statistically small; so if the allocator arranges things such that
> pointers have big integral values, clashes are reduced. Second, in
> many systems all allocated pointers are multiples of four, which
> reduces chances of clash by 75% for random integers. There are many
> tricks like that; I remember just these, but I'm sure gc implementors
> has more up their sleeves.
Independantly of tricks, I believe that Boehm actually did some
statistics on real programs, and found that false addresses were never a
problem. This is a heuristic, but then, we use hash tables and
quicksort, too, and they both depend on "luck" to work well.
There are probably a few applications where the risk of loosing memory
due to a false pointer is simply unacceptable. Just as there are
applications where the risk of taking O(n^2) time because of a bad
initial ordering for a quicksort is not acceptable. Such programs are
few and far between, however, and when the occur, the solution is
known: use something else.
In the mean time, most of us can continue to use hash tables and quick
sort. And conservative garbage collection, if we happen to have it.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> >>ka...@gabi-soft.fr wrote:
> >>>No.
That sounds like a very unusual situation. I've seen a lot of different
applications in my time, and I've yet to see one that wouldn't have been
simpler with garbage collection. And the garbage collection in Java
never caused me any problems.
Note that you shouldn't put on the back of garbage collection poor
programming practices in general. The fact that JFrame.dispose didn't
propagate through all of the owned components did cause me a problem.
Arguably, with explicit memory management, the function would have
propagated, since there would have been no other way to free memory.
But the fact that you don't need to free memory doesn't mean that
objects don't have specific lifetimes. Not propagating this function is
simply bad programming practice, garbage collection or not.
> > Or do you simply do everything in assembler? (Been there. Done
> > that. Don't what to have to do it again.)
> Actually I do my best to make my life as easy as possible which
> includes using a large number of good third party libraries and one of
> my major concerns is what impact allowing your kind of optional GC
> into C++ would have on my ability to select libraries.
Why? The library fulfills a contract. GC is an implementation detail;
it doesn't affect you unless the contract says something about it.
Generally, it simplifies the contract. For a fairly small set of
functions, but still, they are there. (I'm thinking about functions
that have to return values of unknown size. Things like readdir, under
Unix, for example. Take a look at the specifications of readdir and
readdir_r, and you'll see how much easier to use these functions would
be in the presence of garbage collection.)
> > My customers don't pay me to play around. The pay for correctly
> > working programs. And frankly, I'll use any tool that will increase
> > program correctness and/or reduce the amount of effort necessary.
> > What with multithreading and handling asynchronous events in a
> > timely manner, I don't need additional work.
> In that regard I would just love to see all common UNIX versions fully
> support POSIX.
The more things are standardized, the better. Still, I've had less
problems with Posix than with C++. Recently, at least.
> >>This proposal falls in this category. There are legitimate areas
> >>where smart pointers can be helpful but I don't want some junior
> >>programmer adding weird resource management bugs to my code by being
> >>able to use our RAII classes with a GC.
> > You prefer that he add weird resource management bugs without GC?
> > An incompetent programmer is incompetent. Code review and such will
> > soon either improve him, or weed him out. The question is rather
> > how to improve productivity of the vast majority of competent
> > programmers.
> I never said incompetent, I said poor. We try and bring along the
> below average programmer who tries hard and learns while getting rid
> of the truly incompetent ones. However I have found that these sort of
> junior programmers jump on the newest flavor of the month feature in
> the belief that it is a silver bullet and I am in favor of reducing
> the number of different ways these programmers can introduce subtle
> bugs into a project and have found from Java that GC induced bugs are
> usually not easily reproducible and not obvious from examining the
> code that should be the cause of the failure.
That is a real problem, which must be addressed. If you sell garbage
collection as a silver bullet (and it has largely been sold that way in
the Java community), you will have problems. Beware of the silver
bullet boost::shared_ptr, for example. Or the silver bullet of
templates. (The current trend in C++ seems to make everything a
template, even if there is only one type of interest.)
The fact that something isn't a silver bullet shouldn't prevent us from
taking advantage of what it does do for us.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
A GC doesn't only search the heap, and it doesn't search the whole
heap either. It starts with the roots, which are supposed to be all
locations directly accessible by the program now or in the future.
These include the stack, registers and thread-local storage for each
thread, plus static data. It only searches those parts of the heap
that are referred to by the roots (possibly indirectly through other
parts of the heap). If it searched the whole heap then it couldn't
break reference cycles.
Paavo is not quite correct in saying "...somewhere on the heap", but
the misinterpretation of values as pointers is an inherent risk in
using a "conservative" garbage collector as opposed to a "perfect"
garbage collector which knows which words of memory are pointers, and
this can happen in the (apparently) reachable parts of the heap. It
can be reduced by telling the GC allocator which blocks of memory
being allocated will or will not be used to store pointers, and better
still giving it a map of which words of a block will be used to store
pointers. To do that properly requires modifications to the compiler,
though.
The most recent versions of Java fixed the problem but until about 2
years ago the standard GC sweep in Java took over the vm for sometimes
as much as 2 minutes on the 400 MHz PIII that were the standard machines
for one of our web applications. This caused many dropped/refused
connections and browser timeouts, When the techs at the server farm
started investigating why their servers were locking up they came to the
conclusion that we had runaway code somewhere in the app, After several
days searching without success I finally got the techs to open up their
firewall so I could debug one of the servers and found that in the much
more limited resources available to these boxes the GC thread was taking
up to many resources and forcing a great deal of virtual memory swapping
which was the real cause of "lock up", so we had to go into the
application and add a thread to much more frequently trigger the GC
sweep so that the sweep didn't stall out the machines as badly. In the
Java community this sort of problem was well known and caused Sun to put
a lot of effort into improving the GC performance in Java 1.4.
There was also a problem in trying to copy our RAII C++ classes to Java
where C++ Dtor's were used as the basis for Java finalizers which is
obviously wrong and we knew it but it took a code review to catch and
then several man-days correct the problem.
More recently we customized a class loader to allow us to deliver a
large application as an applet but only download the optional packages
on demand. This is actually a pretty good solution to bandwidth issues
with this sort of application but at one point we found ourselves deep
in the reflection weak references weeds which contributed to the project
missing deadline.
> Note that you shouldn't put on the back of garbage collection poor
> programming practices in general. The fact that JFrame.dispose didn't
> propagate through all of the owned components did cause me a problem.
> Arguably, with explicit memory management, the function would have
> propagated, since there would have been no other way to free memory.
> But the fact that you don't need to free memory doesn't mean that
> objects don't have specific lifetimes. Not propagating this function is
> simply bad programming practice, garbage collection or not.
>
Yes it is and various other "zombie" object issues have also at least
cost me unnecessary time thinking through the issue.
>
>>>Or do you simply do everything in assembler? (Been there. Done
>>>that. Don't what to have to do it again.)
>
>
>>Actually I do my best to make my life as easy as possible which
>>includes using a large number of good third party libraries and one of
>>my major concerns is what impact allowing your kind of optional GC
>>into C++ would have on my ability to select libraries.
>
>
> Why? The library fulfills a contract. GC is an implementation detail;
> it doesn't affect you unless the contract says something about it.
>
You are ignoring performance issues and code compatibility issues. What
happens when old library A receives a GC pointer from brand new library
B? If the proposal you favor with different types for GC pointers this
will probably not work.
> Generally, it simplifies the contract. For a fairly small set of
> functions, but still, they are there. (I'm thinking about functions
> that have to return values of unknown size. Things like readdir, under
> Unix, for example. Take a look at the specifications of readdir and
> readdir_r, and you'll see how much easier to use these functions would
> be in the presence of garbage collection.)
>
What I would prefer there and what I have done there is to wrap the
return from readdir into a class so I can don't have to worry about this
anymore.
>
>>>My customers don't pay me to play around. The pay for correctly
>>>working programs. And frankly, I'll use any tool that will increase
>>>program correctness and/or reduce the amount of effort necessary.
>>>What with multithreading and handling asynchronous events in a
>>>timely manner, I don't need additional work.
>
>
>>In that regard I would just love to see all common UNIX versions fully
>>support POSIX.
>
>
> The more things are standardized, the better. Still, I've had less
> problems with Posix than with C++. Recently, at least.
>
It has been a while since I ran into it with C++ but last time I
encountered FreeBSD it didn't have POSIX mutexes.
>
>>>>This proposal falls in this category. There are legitimate areas
>>>>where smart pointers can be helpful but I don't want some junior
>>>>programmer adding weird resource management bugs to my code by being
>>>>able to use our RAII classes with a GC.
>
>
>>>You prefer that he add weird resource management bugs without GC?
>>>An incompetent programmer is incompetent. Code review and such will
>>>soon either improve him, or weed him out. The question is rather
>>>how to improve productivity of the vast majority of competent
>>>programmers.
>
>
>>I never said incompetent, I said poor. We try and bring along the
>>below average programmer who tries hard and learns while getting rid
>>of the truly incompetent ones. However I have found that these sort of
>>junior programmers jump on the newest flavor of the month feature in
>>the belief that it is a silver bullet and I am in favor of reducing
>>the number of different ways these programmers can introduce subtle
>>bugs into a project and have found from Java that GC induced bugs are
>>usually not easily reproducible and not obvious from examining the
>>code that should be the cause of the failure.
>
>
> That is a real problem, which must be addressed. If you sell garbage
> collection as a silver bullet (and it has largely been sold that way in
> the Java community), you will have problems. Beware of the silver
> bullet boost::shared_ptr, for example. Or the silver bullet of
> templates. (The current trend in C++ seems to make everything a
> template, even if there is only one type of interest.)
>
Which is the basic point I'm trying to make. Let's not add features like
this to the standard until some much more basic features are addressed.
In particular an extension of the istream classes to handle http and ftp
for starters. I have an excellent C++ XML library that is stalled
because of the lack of any sort of cross platform way to do a simple
http get. The Java version was completed very quickly because of the
inclusion in the basic API of extension to Java's I/O classes for
exactly this purpose.
> The fact that something isn't a silver bullet shouldn't prevent us from
> taking advantage of what it does do for us.
>
I guess we just will have to disagree on whether this is a good
direction for C++ to go.
Ken
It can be a problem. The allocator tries to work around it by keeping
a "blacklist" of memory blocks whose addresses coincide with
non-pointer values in the program, and stops allocating from those.
(It knows that the values are not pointers if, when interpreted as
pointers, they point to a free part of the block.) See the source
file "blacklst.c".
What I exactly mean is the following,
Var i = 2, j = 3, k;
k = i + j; //this actually an expression
k.evaluate(); //this produce 5
i = 3;
k.evaluate(); //5 or 6, depending on parameter settings.
The parametric behaviour is widely needed in many cases.
For example, defining a force actting on a body.
To define a force, I need to know a point and force value and
direction.
Each dependents can be parametric. This can save a lot of time for the
user and is also more intuitive. In the force definition, if the user
changes the point
definition some time. In paremetric way, he doesn't need to define the
force again. If he change the point definition, he would assume the
force changes too.
There are a lot of dependencies in the input data like this. The
parametric behaviour is best suited in such cases. In C++, this is
best modeled by smart pointers.
Regards
Tony
I do not think so. That is not something I would do with a smart pointer
even though it is possible.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[...]
I'm not saying that the Java garbage collector couldn't cause problems;
I'm just saying it didn't for us. Ours was an interactive application,
and I think that JDK triggers garbage collection if it finds that the
process is otherwise not doing anything. This is a typical situation,
in fact, where a program with garbage collection -- even a fairly
primitive collection like the ones in early versions of Java -- will
have apparently better performance. (You could do something similar
with manual collection -- I once did. But it isn't usual, and none of
the implementations of free or operator delete I know work like this.)
> There was also a problem in trying to copy our RAII C++ classes to
> Java where C++ Dtor's were used as the basis for Java finalizers which
> is obviously wrong and we knew it but it took a code review to catch
> and then several man-days correct the problem.
I'll bet that if you had been porting in the other direction, you'd have
had a lot of problems too:-). Code written for one environment often
doesn't port well to another.
> > Why? The library fulfills a contract. GC is an implementation
> > detail; it doesn't affect you unless the contract says something
> > about it.
> You are ignoring performance issues and code compatibility
> issues. What happens when old library A receives a GC pointer from
> brand new library B? If the proposal you favor with different types
> for GC pointers this will probably not work.
This depends on the proposal. It works with the Detlefs and Ellis
proposal, and with the Boehm collector. It wouldn't work with some of
the other possibilities I've heard mentioned -- I think that in at least
one, whether a pointer was garbage collected or not was a strict part of
the type, and you couldn't assign a garbage collected pointer to a
non-garbage collected pointer, and vice versa.
That's why I categorized garbage collection as being "sort of" part of
the type system in the Detlefs and Ellis proposal. Syntactically, it is
integrated into the type system, but the garbage-collected-ness is
attached to the actual pointer, or pointer value if you prefer. You can
assign a garbage collected pointer to a non-garbage collected pointer
(type), but the garbage collected pointer remains garbage collected.
And you can call free or operator delete on a garbage collected pointer
without harm.
Where there might be a problem is the reverse. The old library returns
a non-garbage collected pointer which it expects you to delete, and you
treat it as a "normal" garbage collected pointer. This will be a
problem as long as old libraries are in existance, but it isn't really
any different than the case today -- you also have to explicitly free
such a pointer.
[...]
> >>I never said incompetent, I said poor. We try and bring along the
> >>below average programmer who tries hard and learns while getting
> >>rid of the truly incompetent ones. However I have found that these
> >>sort of junior programmers jump on the newest flavor of the month
> >>feature in the belief that it is a silver bullet and I am in favor
> >>of reducing the number of different ways these programmers can
> >>introduce subtle bugs into a project and have found from Java that
> >>GC induced bugs are usually not easily reproducible and not obvious
> >>from examining the code that should be the cause of the failure.
> > That is a real problem, which must be addressed. If you sell
> > garbage collection as a silver bullet (and it has largely been sold
> > that way in the Java community), you will have problems. Beware of
> > the silver bullet boost::shared_ptr, for example. Or the silver
> > bullet of templates. (The current trend in C++ seems to make
> > everything a template, even if there is only one type of interest.)
> Which is the basic point I'm trying to make. Let's not add features
> like this to the standard until some much more basic features are
> addressed.
IMHO, garbage collection is one of the more basic features. It's useful
in any program which uses dynamically allocated memory, and that's quite
a few.
> In particular an extension of the istream classes to handle http and
> ftp for starters. I have an excellent C++ XML library that is stalled
> because of the lack of any sort of cross platform way to do a simple
> http get. The Java version was completed very quickly because of the
> inclusion in the basic API of extension to Java's I/O classes for
> exactly this purpose.
Now that sounds like something exotic. Although sockets are becoming
universal enough that I wouldn't object to a TCP stream, I'm very
dubious about the necessity of adding support for the individual
protocols. Why HTTP and not SMTP, for example? (My current project
sends email in case of problems; it doesn't do anything in HTTP.)
> > The fact that something isn't a silver bullet shouldn't prevent us
> > from taking advantage of what it does do for us.
> I guess we just will have to disagree on whether this is a good
> direction for C++ to go.
And I rather suspect that neither of us will have much influence on the
final decision:-).
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
ka...@gabi-soft.fr wrote:
Maybe it does in Java 1.4 before then it did not.
If you examine the XML standard you will find a requirement that a
parser needs to be able to get a document from a specified URI. I didn't
leave out SMTP for any reason I just included the protocols I most
recently needed cross platform support for. I'm sure other people who
develop for multiple platforms have run into this issue and have had to
come up with any number of ad hoc solutions rather than being able to
use the standard library which should supply the basic resources
necessary for most any application.
Ken
[...]
> > > In particular an extension of the istream classes to handle http
> > > and ftp for starters. I have an excellent C++ XML library that is
> > > stalled because of the lack of any sort of cross platform way to
> > > do a simple http get. The Java version was completed very quickly
> > > because of the inclusion in the basic API of extension to Java's
> > > I/O classes for exactly this purpose.
> > Now that sounds like something exotic. Although sockets are
> > becoming universal enough that I wouldn't object to a TCP stream,
> > I'm very dubious about the necessity of adding support for the
> > individual protocols. Why HTTP and not SMTP, for example? (My
> > current project sends email in case of problems; it doesn't do
> > anything in HTTP.)
> If you examine the XML standard you will find a requirement that a
> parser needs to be able to get a document from a specified URI.
Fine, but for most C++ applications, XML is something pretty exotic.
> I didn't leave out SMTP for any reason I just included the protocols I
> most recently needed cross platform support for. I'm sure other
> people who develop for multiple platforms have run into this issue and
> have had to come up with any number of ad hoc solutions rather than
> being able to use the standard library which should supply the basic
> resources necessary for most any application.
Sure. Depending on what you do, you might need one or more Internet
protocols. Or you might not -- I'd guess that less than 10% of the
computers in the world are connected to Internet. It remains a special
interest -- the only Internet protocols my current application uses is
SMTP and FTP; the previous application used RADIUS, and before that,
I've written code using HTTP, SMTP, NNTP... But I would hardly claim
that any of these fulfills a univeral need for C++ programmers.
That doesn't mean that they can't possibly be candidates for
standardization -- not every program needs std::complex, either. But
they still seem rather special interest.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
ka...@gabi-soft.fr wrote:
> Ken Shaw <non...@your.biz> wrote in message
> news:<zcM%b.49956$aH3.1...@bgtnsc04-news.ops.worldnet.att.net>...
>
> [...]
> > > > In particular an extension of the istream classes to handle http
> > > > and ftp for starters. I have an excellent C++ XML library that is
> > > > stalled because of the lack of any sort of cross platform way to
> > > > do a simple http get. The Java version was completed very quickly
> > > > because of the inclusion in the basic API of extension to Java's
> > > > I/O classes for exactly this purpose.
>
> > > Now that sounds like something exotic. Although sockets are
> > > becoming universal enough that I wouldn't object to a TCP stream,
> > > I'm very dubious about the necessity of adding support for the
> > > individual protocols. Why HTTP and not SMTP, for example? (My
> > > current project sends email in case of problems; it doesn't do
> > > anything in HTTP.)
>
> > If you examine the XML standard you will find a requirement that a
> > parser needs to be able to get a document from a specified URI.
>
> Fine, but for most C++ applications, XML is something pretty exotic.
The point is that many technologies C++ should interface with require
basic internet capabilities.
>
> > I didn't leave out SMTP for any reason I just included the protocols I
> > most recently needed cross platform support for. I'm sure other
> > people who develop for multiple platforms have run into this issue and
> > have had to come up with any number of ad hoc solutions rather than
> > being able to use the standard library which should supply the basic
> > resources necessary for most any application.
>
> Sure. Depending on what you do, you might need one or more Internet
> protocols. Or you might not -- I'd guess that less than 10% of the
> computers in the world are connected to Internet. It remains a special
> interest -- the only Internet protocols my current application uses is
> SMTP and FTP; the previous application used RADIUS, and before that,
> I've written code using HTTP, SMTP, NNTP... But I would hardly claim
> that any of these fulfills a univeral need for C++ programmers.
>
> That doesn't mean that they can't possibly be candidates for
> standardization -- not every program needs std::complex, either. But
> they still seem rather special interest.
>
I don't know or care what percentage of computers are connected to the
internet what I care about are the requirements of the applications I
write. It has been more than 5 years since I wrote an application that
wasn't required to use one of the internet protocols. There are many
sections of the standard library that are of rather narrow interest and
if you examine the C++ Library extensions proposed by the LWG of the
standards committee, you will find some extremely narrow items being
added to the standard library.
Ken
> > [...]
> > > > > In particular an extension of the istream classes to handle
> > > > > http and ftp for starters. I have an excellent C++ XML
> > > > > library that is stalled because of the lack of any sort of
> > > > > cross platform way to do a simple http get. The Java version
> > > > > was completed very quickly because of the inclusion in the
> > > > > basic API of extension to Java's I/O classes for exactly
> > > > > this purpose.
> > > > Now that sounds like something exotic. Although sockets are
> > > > becoming universal enough that I wouldn't object to a TCP
> > > > stream, I'm very dubious about the necessity of adding support
> > > > for the individual protocols. Why HTTP and not SMTP, for
> > > > example? (My current project sends email in case of problems;
> > > > it doesn't do anything in HTTP.)
> > > If you examine the XML standard you will find a requirement that
> > > a parser needs to be able to get a document from a specified URI.
> > Fine, but for most C++ applications, XML is something pretty exotic.
> The point is that many technologies C++ should interface with require
> basic internet capabilities.
I'm not even sure about that, but "basic internet capabilities" do not
include XML -- I'd say that a reasonable socket interface would do for
starters. As I said, XML is something extremely exotic, only relevant
for certain very limited niches.
If you accept the idea that a standard C++ library should support the
internet (and I'm not convinced that it should), then you need first of
all support for TCP and UDP -- the socket layer under Unix and Windows.
Beyond that, by far the most relevant protocol would be DNS, except that
you probably shouldn't define the interface as a protocol. At the very
limit, some support of Internet ASCII, quoted printable and UTF-8.
Note, however, that the framework for the last three exists already --
if they can't be handled by means of the codecvt facet of an embedded
locale, then something is seriously wrong. For that matter, there is
nothing in the standard which forbids fstream from understanding a full
URL as its "filename". If it isn't currently the case with your
compiler, change compilers. If you can't find a compiler which does it,
then it would appear that there is no significant market demand for it.
As for higher level protocols in general, there are too many to
standardize, and any choice would be necessarily arbitrary.
> > > I didn't leave out SMTP for any reason I just included the
> > > protocols I most recently needed cross platform support for. I'm
> > > sure other people who develop for multiple platforms have run
> > > into this issue and have had to come up with any number of ad hoc
> > > solutions rather than being able to use the standard library
> > > which should supply the basic resources necessary for most any
> > > application.
> > Sure. Depending on what you do, you might need one or more Internet
> > protocols. Or you might not -- I'd guess that less than 10% of the
> > computers in the world are connected to Internet. It remains a
> > special interest -- the only Internet protocols my current
> > application uses is SMTP and FTP; the previous application used
> > RADIUS, and before that, I've written code using HTTP, SMTP, NNTP...
> > But I would hardly claim that any of these fulfills a univeral need
> > for C++ programmers.
> > That doesn't mean that they can't possibly be candidates for
> > standardization -- not every program needs std::complex, either.
> > But they still seem rather special interest.
> I don't know or care what percentage of computers are connected to the
> internet what I care about are the requirements of the applications I
> write.
Understandable. But you can't really expect the standard to endorse all
of the minor requirements of your implementation. Why XML, when XDR and
probably BER are more widespread. (Of the three, IMHO, only XDR comes
anywhere close to being widely enough used to justify standardization,
and even it falls short.)
> It has been more than 5 years since I wrote an application that wasn't
> required to use one of the internet protocols.
I could say the same. Except that in my case, the time span is closer
to ten years. However, the protocols have varied: SMTP is usually
present, albeit only for error reporting, and FTP has certainly been the
second most prevelant. And quite a few less frequent protocols. In
fact, about the only protocol present in every application has been DNS,
although we generally only accessed it via the Posix interface
gethostbyname().
Still, I very much doubt that the program which controls the ABS in my
car's brakes is connected to the Internet. And such embedded processors
make up by far the largest number. As to what programmers are actually
doing, it is more difficult to say -- the large number of embedded
processors is partially offset by the fact that many of them run the
same program, and that that program is relatively small compared to some
other things.
> There are many sections of the standard library that are of rather
> narrow interest and if you examine the C++ Library extensions proposed
> by the LWG of the standards committee, you will find some extremely
> narrow items being added to the standard library.
I'll admit that I haven't looked lately. I was under the impression
that most of what was being considered was of a more general interest --
what we would consider programming technology, rather than anything
domain specific. Things like threading, or regular expressions, which
will be used in a large variety of domains.
That said, I'm not sure that I could really define my criteria
rationally. As I said, complex is of interest only to a relatively
limited domain, and yet for reasons I can't explain myself, it seems
natural to me that it be in the standard. Where as I'm not pushing to
see any official support for TCP/IP, although the interest is
doubtlessly more general.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
That appears to rely on instantiating one dummy object of each type
that can be allocated on the GC heap, which is not, in general,
acceptable.
The issue is not whether a certain compiler supports URI filenames in
fstream, it is whether enough do that so I can write code in a cross
platform and cross compiler manner. Unfortunately this doesn't exist and
it seems to be a place where the standard should provide guidance.
Want to bet that now or in the very near future the various CPU's in
your car will be able to communicate by TCP/IP? You might want to talk
to a serious gear head before answering.
>
>>There are many sections of the standard library that are of rather
>>narrow interest and if you examine the C++ Library extensions proposed
>>by the LWG of the standards committee, you will find some extremely
>>narrow items being added to the standard library.
>
>
> I'll admit that I haven't looked lately. I was under the impression
> that most of what was being considered was of a more general interest --
> what we would consider programming technology, rather than anything
> domain specific. Things like threading, or regular expressions, which
> will be used in a large variety of domains.
>
Here is a link to what is being proposed:
http://std.dkuug.dk/jtc1/sc22/wg21/docs/library_technical_report.html
While I think some of these topics are good ideas for inclusion. I think
tuples, math special functions and random number proposals are much more
narrow in purpose than internet protocols.
> That said, I'm not sure that I could really define my criteria
> rationally. As I said, complex is of interest only to a relatively
> limited domain, and yet for reasons I can't explain myself, it seems
> natural to me that it be in the standard. Where as I'm not pushing to
> see any official support for TCP/IP, although the interest is
> doubtlessly more general.
>
While I'm not in favor of a standard library with the scope of Java's I
certainly think that the standard library needs to be more supportive of
general application programming tasks.
Ken
I think this entire post reflects a dangerous attitude. Even more so because
it comes from a influential member of the community and is articulated with
so much conviction. Seriously. If things like networking --- that are a
given in so many current and popular languages --- are considered to be too
narrow, specific, or unimportant to be considered for C++ standardization,
then programmers will flock to those other languages.
Berkeley Sockets, a de facto standard with a C binding, has helped the
situation in the past. But look just how *easy* libraries of Java and C#
make it to do really cool networking stuff. If I'd start a new networking
app (as are a lot), what incentive do I have to program it in standard C++?
Write my own wrappers for sockets and parsers for HTTP? Well one can fetch a
page in C# in three lines.
Networking *is* important, and I believe it will become more important, not
less. There is a proposal for special "Mathematical Special Functions" in
C++ (http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1422.html). Why
would the special mathematical functions be part of the future standard and
not some much more common networking primitives? Coz honestly, not only I
never used a cylindrical Neumann function, but I can't tell it from a ground
in the hole. Or vice versa. (I got confused.) Yet I guess all who are going
to read this post and/or reply to it will be using some sort of networking
:o).
Andrei
The way things work with ISO standard, or at least with the C++ standard,
is that people write proposals which are then considered by the committee.
I can't remember a proposal addressing any socket layer although I'm aware
of several implementation of sockets. If you are interested in this stuff
becoming standardized, write a proposal.
Whether a proposal for something will be accepted depends on how it fits
into the overall system and whether there are people behind it. A problem
I see with something like sockets is that it is not applicable to all
systems and that there are considerable differences between different
systems supporting it. The first issue calls for something like an optional
library component but currently we don't have any concept for something
like this (well, except the hosted and freestanding distinction). The
differences between systems seem to ask for different approaches on
different systems which would effectively mean that if the component is
optional, vendors would opt for not providing it but rather using their
custom interfaces.
--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
Andrei Alexandrescu wrote:
Is there anyone that would like to collaborate on a stream based
networking proposal? While I can certainly lay out the top level
interface I don't know enough about the low level requirements of such
an interface.
Ken
Yes, I agree but the problem is that WG21 always works on the basis of
volunteers to do the work (and even then they have to persuade the rest
that the work is worth incorporating into the C++ Standard.)
I am certain that there are a number of things that would make C++ more
attractive to many ordinary programmers. There are also several things
that would make C++ easier to teach and easier to learn. Some of those
extras have little or no value to the expert programmer while retaining
considerable utility to the incidental programmer (the one who needs to
program as a consequence of their main work or interests). Such people
do not have time to go searching for suitably high quality third party
libraries that meet their needs (I think those members of WG21 who
lunched with some astronomers in Hawaii last October might appreciate
that)
There are various small changes we can consider to the core of the
language that will help many programmers. There are a few things that we
can add to the library that would have wide ranging utility (note that
those advanced math functions are currently only part of a TR).
However I wonder if there is some merit in considering a TR aimed at
teaching C++. Something a bit like the performance TR but also
incorporating a number of libraries that we might not want to add to the
Standard but which nonetheless would assist both those learning C++ and
incidental programmers.
I know we are now working on the next release of C++ (aimed at around
2008/9) but I do not see that that should prohibit us working on a TR as
well.
What do others think?
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[...]
> > Note, however, that the framework for the last three exists already
> > -- if they can't be handled by means of the codecvt facet of an
> > embedded locale, then something is seriously wrong. For that
> > matter, there is nothing in the standard which forbids fstream from
> > understanding a full URL as its "filename". If it isn't currently
> > the case with your compiler, change compilers. If you can't find a
> > compiler which does it, then it would appear that there is no
> > significant market demand for it.
> The issue is not whether a certain compiler supports URI filenames in
> fstream, it is whether enough do that so I can write code in a cross
> platform and cross compiler manner. Unfortunately this doesn't exist
> and it seems to be a place where the standard should provide guidance.
It's a quality of implementation issue. If enough compilers don't
support it, it is doubtlessly because most people don't consider it
important.
> > I'll admit that I haven't looked lately. I was under the impression
> > that most of what was being considered was of a more general
> > interest -- what we would consider programming technology, rather
> > than anything domain specific. Things like threading, or regular
> > expressions, which will be used in a large variety of domains.
> Here is a link to what is being proposed:
> http://std.dkuug.dk/jtc1/sc22/wg21/docs/library_technical_report.html
> While I think some of these topics are good ideas for inclusion. I
> think tuples, math special functions and random number proposals are
> much more narrow in purpose than internet protocols.
Than the protocols, I would disagree. Than basic IP/TCP support,
probably not. There are historical factors involved as well -- math
functions have always pretty much been an integral part of C (and of
most other programming languages, except COBOL, as well) -- extending
them seems somehow reasonable, even if most programs don't do much in
the way of math. Ditto random.
> > That said, I'm not sure that I could really define my criteria
> > rationally. As I said, complex is of interest only to a relatively
> > limited domain, and yet for reasons I can't explain myself, it seems
> > natural to me that it be in the standard. Where as I'm not pushing
> > to see any official support for TCP/IP, although the interest is
> > doubtlessly more general.
> While I'm not in favor of a standard library with the scope of Java's
> I certainly think that the standard library needs to be more
> supportive of general application programming tasks.
And I'm not convinced that any one protocol is part of the "general
application programming tasks".
I do think that there is a strong argument for TCP and UCP support
(sockets under Unix and Windows). Given portable TCP support, it is
relatively easy to write a portable implementation of, say, SMTP, using
standard C++, and nothing else. On the other hand, there is no portable
way, today, to interface to sockets (or whatever is necessary for TCP or
UCP). I'm actually rather surprised that Boost doesn't have something
for this.
My current position is fairly simple: there are two extensions which
must be taken into account somehow, because they have implications with
regards to the language itself: threading and dynamic linking. There
are also two components in Boost (and perhaps in the library technical
support) which are really language issues, and should be solved at the
language level, and not by library hacks, no matter how brilliant: smart
pointers (which should be made caduc by standardizing garbage
collection), and the lambda library (which is also better handled as
part of the language).
That said, of course, there is no hurry. Compilers still don't
implement the current version of the standard; there's no point in
creating a new version until they are at least capable of supporting the
current one.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[...]
Aren't you putting the cart before the horse? Is your goal to build a
network application? Or is it to use C++ regardless of what it is you're
building?
-thant
As has been pointed out before, I don't see any great distinction
between assuming that fstream's make sense on a particular platform,
and assuming that socket's might.
One the big problems I've seen with poor standard C++ support for
common operations like networking, file system handling, threading
etc. etc., is that nearly all the popular fully-fledged cross-platform
C++ libraries that support these things are a) way too big and b) not
particularly compatible with the existing C++ standard library. Many
of them provide and are extensively tied to their own string and
collection classes, and rarely if ever provide features like templates
and iterators that are arguably the true powerhouse of modern standard
C++. Boost is of course an exception here.
Maybe some sort of basic standard specification for the most common of
these functionalities would help push library writers in the right
direction, but it's hard to imagine what sort of form it would take.
Dylan
If that was sniping: <censored>
If that was an honest question: The idea was contemplating language choices
for writing an application that has networking as a part of it, with the
team at hand and under whatever other constraints.
Andrei
That's a great way of getting things done, unfortunately it has the downside
that what makes it into the standard is composed of things that people with
dedication considered useful, interesting, challenging, fun to work on, or
some weighted combination of the above. These features form a set that
intersects but might not include the features that the large C++ community
needs. Worse, this large community sometimes might not reply by trying to
increase awareness; they need to get the job done, and they'll just look for
something that works. That is some nonstandard library or even another
language that offers more.
I'd feel sorry if networking would fall through the cracks.
> I am certain that there are a number of things that would make C++ more
> attractive to many ordinary programmers. There are also several things
> that would make C++ easier to teach and easier to learn. Some of those
> extras have little or no value to the expert programmer while retaining
> considerable utility to the incidental programmer (the one who needs to
> program as a consequence of their main work or interests). Such people
> do not have time to go searching for suitably high quality third party
> libraries that meet their needs (I think those members of WG21 who
> lunched with some astronomers in Hawaii last October might appreciate
> that)
I wouldn't think networking is just a little extra that would help beginner
programmers and make learning for them more fun. ("Look, ma, I remotely
connected to your machine and installed a trojan there! And it's all
standard C++!") I enjoy thinking I finally passed the beginner C++ stage,
yet when I asked myself to write an email filtering system, I did some
research on the Net and C++ was among the least convenient languages, unless
I planned to use a not-so-nicely designed library, or to start wrapping
SOCKETs myself.
Andrei
> I think this entire post reflects a dangerous attitude. Even more so
> because it comes from a influential member of the community and is
> articulated with so much conviction. Seriously. If things like
> networking --- that are a given in so many current and popular
> languages --- are considered to be too narrow, specific, or
> unimportant to be considered for C++ standardization, then programmers
> will flock to those other languages.
Let's put it in context, and not have me saying more than I meant to
say. Networking is certainly an important part of computing, as are
data bases, GUI's and a lot of other things. And as I think I said,
some sort of standard interface for TCP/IP, UDP/IP and DNS functionality
would IMHO be acceptable candidates for standardization if someone
wanted to make a proposal.
On the other hand, I don't see the C++ standard trying to support every
protocol around. If you want to support protocols, which ones: my last
application used RADIUS, for example, which is hardly the case of every
application. The original comment concerned XML -- I've yet to find any
use for that one.
> Berkeley Sockets, a de facto standard with a C binding, has helped the
> situation in the past. But look just how *easy* libraries of Java and
> C# make it to do really cool networking stuff.
I don't know about C#, but Java is really a niche language. It is easy
to do a lot of networking stuff, yes, but it is difficult to do anything
else. Without the networking support, Java would be dead today.
I don't think that C++ is in the same situation. Unlike Java, C++ is a
very general purpose language. When you want to use it for some
specific application, you almost always have to incorporate other
libraries. For networking, if that's what your doing, but also for data
base access, for file management, for threading, for a GUI, for ...
> If I'd start a new networking app (as are a lot), what incentive do I
> have to program it in standard C++?
The fact that you have a good third party library which supports it:-)?
> Write my own wrappers for sockets and parsers for HTTP? Well one can
> fetch a page in C# in three lines.
> Networking *is* important, and I believe it will become more
> important, not less. There is a proposal for special "Mathematical
> Special Functions" in C++
> (http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1422.html). Why
> would the special mathematical functions be part of the future
> standard and not some much more common networking primitives?
Historical reasons:-). For some reason, all languages (except Cobol)
seem to want to support numerics intensively.
> Coz honestly, not only I never used a cylindrical Neumann function,
> but I can't tell it from a ground in the hole. Or vice versa. (I got
> confused.) Yet I guess all who are going to read this post and/or
> reply to it will be using some sort of networking :o).
And I guess most of them will be using one of about two or three
different programs to do so. Surely your argument isn't that because
something is important for three different programs, it needs to be in
the standard:-).
And I sort of agree with you concerning the mathematical functions: I've
yet to use double for any real programming, much less any of the more
elaborate stuff. On the other hand, one of the justifications of
standardizing something is that it cannot be done efficiently in a
portable manner in the language itself. Since a correct version of most
numeric functions requires some understanding of the actual
representation of the underlying types -- something which intrinsically
isn't portable. So there is some justification. Similar justification
would apply to support for TCP or UDP.
----
I think that there is an interesting point here to be considered. Not
networking, per se, but rather, what should the goal of the C++ standard
be. In itself, I could very well see a standard that encompassed
networking, in all of its forms, a GUI, data base access, hard real time
programming, and a lot of other things. Realistically, however, very
few, if any, implementations will be able to support them all : you
can't do hard real time under Windows or any of the common Unixes, for
example. IMHO, there is first and foremost a meta-question here: how do
we handle large blocks of complex functionality which isn't relevant to
some platforms. The example of time() isn't really relevant here -- it
is an isolated function. And my feeling is that the two-fold
distinction hosted/free standing isn't really sufficient if we start
adding GUI's, networking, and the rest. On the other hand, the machines
I program on do have GUI's, and network connections, and it's definitly
true that life would be easier for me if there were a standard way of
addressing them; I'm as tired of maintaining multiple sub-directories,
one per platform, as you are. While my need for RADIUS in my last
project was probably rather exceptional, it's been years since I've
written a project which didn't use SMTP, and I suspect HTTP and FTP are
also pretty common requirements.
So what am I arguing about. Two things, really:
- These extensions shouldn't let us lose sight of the more general
issued -- garbage collection is certainly a lot more important and
of more use to more different applications, real support for
something along the lines of lamda classes or nested functions would
be of more general impact, and anything that makes generic
programming more accessible to the average programmer will (or
should) affect just about every application domain.
- In no case should we arrive at a situation in which any system which
supported, say fstream, would be required to support all of the
above. IMHO, networking protocols, a GUI and data base access (to
name but three) are only acceptable if we can develop some sort of
mechanism for "optional" packages. For the moment, all we have is
hacks (and non-conformant implementations, and "implementation
defined" behavior which stretches the English language to its
utmost).
Also, I might repeat my above point: what cannot be easily and portably
expressed in the language itself must be part of the standard, so that I
have a portable interface to it. While I already mentionned garbage
collection and lambda programming above, probably the most important
feature that we cannot require everywhere is threading, and that also
impacts on the language itself, and not just libraries. Which makes me
think that my second point above must be addressed, imperatively.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> Is there anyone that would like to collaborate on a stream based
> networking proposal? While I can certainly lay out the top level
> interface I don't know enough about the low level requirements of such
> an interface.
Isn't that putting the cart before the horse? What do you mean by
"networking"?
To implement most protocols, I need access to either TCP or UDP -- TCP
can be modeled as a stream (I presume you mean iostreams), sort of, but
I'm not sure that the model is optimmal. UDP is anything but a stream.
Generally speaking, regardless of the protocol, you need DNS before
initializing it. There again, I don't think that the stream interface
is appropriate, although something more than gethostbyname is certainly
in order.
As for the higher level protocols, most of them don't really map to a
stream interface either, at least not in their entirity. On the other
hand, it might be interesting to integrate some of them into fstream:
std::ofstream message( "myFile.txt" ) ;
// File...
std::ofstream message( "! gzip > myFile.txt" ) ;
// Pipes the output through gzip...
std::ofstream message( "mailto:ka...@gabi-soft.fr" ) ;
// Sends email -- under Unix, at
// least, this does NOT involve
// networking.
std::ofstream message( "ftp://your.machine.com/filename.txt" ) ;
// Transfers the data via FTP...
etc., etc.
Is this what you had in mind? One thing about it, the error management
in ostream is really way to course for this. You need to find some
better way to report errors.
Finally, there are a number of useful functionalities which are common
to several protocols: things like Internet ASCII and quoted-printable,
for example. I suppose that they could partially be handled by locale
(the codecvt facet), but if you go that route, you should probable clean
up the locale stuff a bit, to make it more generally useable. Thus, for
example, a filebuf shouldn't contain a locale, and the only excuse for
it being a template is if the underlying OS can output different sized
types. Although, Windows not withstanding, most programming languages
tend to assume that IO is strictly in bytes. On the other hand, you
need some sort of filtering streambuf which will handle the transcoding
-- you might insert a printed-quotable streambuf in front of the SMTP
streambuf if you wanted to output Unicode to email, for example.
IMHO, such functionalities should precede any attempt to handle email or
web pages directly.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
I am probably odd in this regard, but I would rather see higher level
networking functions (that is, http, ftp etc) than the lower level
functions. The low level is too OS dependent to be efficiently
abstracted. For example, on Windows, to get good throughput, you
really want to use connection points and the asynchronous networking
apis. The BSD emulation under windows is much less efficient.
Whereas, under unix they don't really have these apis. However, the
higher level operations like get a page or get a file from this system
could be implemented efficiently everywhere. Combine that with http
parsers (like python has for example) and you have a system where you
can do some pretty cool things without sacrificing efficiency.
>
> Networking *is* important, and I believe it will become more important, not
> less. There is a proposal for special "Mathematical Special Functions" in
> C++ (http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1422.html). Why
> would the special mathematical functions be part of the future standard and
> not some much more common networking primitives? Coz honestly, not only I
> never used a cylindrical Neumann function, but I can't tell it from a ground
> in the hole. Or vice versa. (I got confused.) Yet I guess all who are going
> to read this post and/or reply to it will be using some sort of networking
> :o).
I have to agree that I don't see the point in standardizing and
forcing every compiler implementer to provide things like this or even
the complex type for that matter. However, I can easily ignore them.
There deserves to be separate library specs that aren't as tightly
bound to the compiler for things that don't require specific compiler
support. Some of the optional libraries would probably be so commonly
used that all compiler vendors will provide them, but others would
not. Networking, threading, advanced math could probably be option
libraries. On the other hand, there are things that need integration
with the compiler like GC and built-in lambda functionality.
just my $.02
Joe Greer
I don't think fstream should support URIs as filenames because that's
not enough to be generally useful. A URI identifies a resource which
can have several byte streams (entities) associated with it. A
request to "get" that resource can include many parameters that affect
the selection of the entity returned, such as Accept-Language in HTTP
or file type in FTP, plus authentication information. Proper support
for HTTP and FTP streams must allow the application to set such
parameters and to use POST requests in HTTP.
I'd like to see something along the lines of Python's urllib2 (see
<http://www.python.org/doc/2.3/lib/module-urllib2.html> and
<http://www.python.org/doc/2.3/lib/request-objects.html>), though
not in the standard library.
>> > I'll admit that I haven't looked lately. I was under the impression
>> > that most of what was being considered was of a more general
>> > interest -- what we would consider programming technology, rather
>> > than anything domain specific. Things like threading, or regular
>> > expressions, which will be used in a large variety of domains.
>
>> Here is a link to what is being proposed:
>> http://std.dkuug.dk/jtc1/sc22/wg21/docs/library_technical_report.html
>
>> While I think some of these topics are good ideas for inclusion. I
>> think tuples, math special functions and random number proposals are
>> much more narrow in purpose than internet protocols.
>
> Than the protocols, I would disagree. Than basic IP/TCP support,
> probably not. There are historical factors involved as well -- math
> functions have always pretty much been an integral part of C (and of
> most other programming languages, except COBOL, as well) -- extending
> them seems somehow reasonable, even if most programs don't do much in
> the way of math. Ditto random.
Plus they don't require any underlying OS or hardware support (though
a floating-point unit is very helpful and many embedded processors
don't have them).
>> > That said, I'm not sure that I could really define my criteria
>> > rationally. As I said, complex is of interest only to a relatively
>> > limited domain, and yet for reasons I can't explain myself, it seems
>> > natural to me that it be in the standard. Where as I'm not pushing
>> > to see any official support for TCP/IP, although the interest is
>> > doubtlessly more general.
>
>> While I'm not in favor of a standard library with the scope of Java's
>> I certainly think that the standard library needs to be more
>> supportive of general application programming tasks.
>
> And I'm not convinced that any one protocol is part of the "general
> application programming tasks".
>
> I do think that there is a strong argument for TCP and UCP support
You mean UDP, not UCP.
> (sockets under Unix and Windows). Given portable TCP support, it is
> relatively easy to write a portable implementation of, say, SMTP, using
> standard C++, and nothing else. On the other hand, there is no portable
> way, today, to interface to sockets (or whatever is necessary for TCP or
> UCP). I'm actually rather surprised that Boost doesn't have something
> for this.
I think I agree with you here. I think most new desktop and server
applications will make some use of HTTP but in many cases that will be
indirect use through a web browser or an application server so that
the application doesn't need to speak the protocol itself. So while
I'd be glad to see HTTP support in Boost I don't feel it belongs in
the standard library.
<snip>
> That said, of course, there is no hurry. Compilers still don't
> implement the current version of the standard; there's no point in
> creating a new version until they are at least capable of supporting the
> current one.
I think we'll be waiting a very long time for "export".
ka...@gabi-soft.fr wrote:
> Ken Shaw <non...@your.biz> wrote in message
> news:<8fn1c.68432$aH3.2...@bgtnsc04-news.ops.worldnet.att.net>...
>
>
>>Is there anyone that would like to collaborate on a stream based
>>networking proposal? While I can certainly lay out the top level
>>interface I don't know enough about the low level requirements of such
>>an interface.
>
>
> Isn't that putting the cart before the horse? What do you mean by
> "networking"?
>
> To implement most protocols, I need access to either TCP or UDP -- TCP
> can be modeled as a stream (I presume you mean iostreams), sort of, but
> I'm not sure that the model is optimmal. UDP is anything but a stream.
>
TCP/IP should not be modeled at the stream level but included as part
the underlying infrastructure. I have never needed to use UDP and am
unfamiliar with it's underlying details which is why I asked for a
collaborator.
> Generally speaking, regardless of the protocol, you need DNS before
> initializing it. There again, I don't think that the stream interface
> is appropriate, although something more than gethostbyname is certainly
> in order.
>
> As for the higher level protocols, most of them don't really map to a
> stream interface either, at least not in their entirity. On the other
> hand, it might be interesting to integrate some of them into fstream:
>
> std::ofstream message( "myFile.txt" ) ;
> // File...
> std::ofstream message( "! gzip > myFile.txt" ) ;
> // Pipes the output through gzip...
This seems to be an attempt to shoehorn a shell command into an
inappropriate place.
> std::ofstream message( "mailto:ka...@gabi-soft.fr" ) ;
> // Sends email -- under Unix, at
> // least, this does NOT involve
> // networking.
It doesn't? Delete the socket layer software on your unix box and see
how well this works.
> std::ofstream message( "ftp://your.machine.com/filename.txt" ) ;
> // Transfers the data via FTP...
>
> etc., etc.
>
> Is this what you had in mind? One thing about it, the error management
> in ostream is really way to course for this. You need to find some
> better way to report errors.
Error handling/reporting is one of the issues I feel would be the
hardest to get right.
>
> Finally, there are a number of useful functionalities which are common
> to several protocols: things like Internet ASCII and quoted-printable,
> for example. I suppose that they could partially be handled by locale
> (the codecvt facet), but if you go that route, you should probable clean
> up the locale stuff a bit, to make it more generally useable.
I have used codecvt for this exact purpose on a number of occasions and
see no reason it could not be used for this purpose again here.
Thus, for
> example, a filebuf shouldn't contain a locale, and the only excuse for
> it being a template is if the underlying OS can output different sized
> types. Although, Windows not withstanding, most programming languages
> tend to assume that IO is strictly in bytes. On the other hand, you
> need some sort of filtering streambuf which will handle the transcoding
> -- you might insert a printed-quotable streambuf in front of the SMTP
> streambuf if you wanted to output Unicode to email, for example.
>
> IMHO, such functionalities should precede any attempt to handle email or
> web pages directly.
Since you are not interested in the development of such a networking
proposal why are you even bothering to reply to this post?
Ken
> That's a great way of getting things done, unfortunately it has the
> downside that what makes it into the standard is composed of things
> that people with dedication considered useful, interesting,
> challenging, fun to work on, or some weighted combination of the
> above. These features form a set that intersects but might not include
> the features that the large C++ community needs. Worse, this large
> community sometimes might not reply by trying to increase awareness;
> they need to get the job done, and they'll just look for something
> that works. That is some nonstandard library or even another language
> that offers more.
It's not quite that bad:-).
You have to remember that many of the committee members are in fact
compiler vendors. And that the standard is not really the end for
them -- it is a means. The end is to sell more compilers. A large user
base for C++ is part of the means, and an efficient, usable standard is
a a means to increase the user base. So while it is true that there is
very little direct representation of users on the committee, they are
fairly effectively represented indirectly via the vendors. It's far
from perfect, but until someone can convince the end user companies that
it is in their interest as well to donate time and effort, it's all
we've got.
[...]
> I wouldn't think networking is just a little extra that would help
> beginner programmers and make learning for them more fun. ("Look, ma,
> I remotely connected to your machine and installed a trojan there! And
> it's all standard C++!") I enjoy thinking I finally passed the
> beginner C++ stage, yet when I asked myself to write an email
> filtering system, I did some research on the Net and C++ was among the
> least convenient languages, unless I planned to use a not-so-nicely
> designed library, or to start wrapping SOCKETs myself.
Networking is a vast domain. I don't think we need an XLM parser in the
standard just yet:-). Your complaint about no portable way of using
sockets is, fully justified, and IMHO should be addressed by the
standard. See my other posting, however: I think we need to address the
problem of optional packages first.
Another thing that someone should probably address is getting the
implementors to implement the standard. There's no point in
standardizing anything if it ends up like export, or even the name
lookup rules in templates. For the moment, I would consider getting
implementation to conform to the current standard far more important
than adding new features, no matter how important or useful the new
features may be.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
|> ka...@gabi-soft.fr wrote:
|> > To implement most protocols, I need access to either TCP or UDP --
|> > TCP can be modeled as a stream (I presume you mean iostreams),
|> > sort of, but I'm not sure that the model is optimmal. UDP is
|> > anything but a stream.
|> TCP/IP should not be modeled at the stream level but included as
|> part the underlying infrastructure. I have never needed to use UDP
|> and am unfamiliar with it's underlying details which is why I asked
|> for a collaborator.
I'll bet you have. Most implementations of DNS still use it, so if
you've ever called gethostbyname() (or its equivalent under
Windows)... :-)
|> > Generally speaking, regardless of the protocol, you need DNS
|> > before initializing it. There again, I don't think that the
|> > stream interface is appropriate, although something more than
|> > gethostbyname is certainly in order.
|> > As for the higher level protocols, most of them don't really map
|> > to a stream interface either, at least not in their entirity. On
|> > the other hand, it might be interesting to integrate some of them
|> > into fstream:
|> > std::ofstream message( "myFile.txt" ) ;
|> > // File...
|> > std::ofstream message( "! gzip > myFile.txt" ) ;
|> > // Pipes the output through gzip...
|> This seems to be an attempt to shoehorn a shell command into an
|> inappropriate place.
It could easily be used for that:-). I explicitly chose the case of
gzip, however, because it is a case where we really are using streaming
output. Instead of putting the compression in a filtering streambuf, I
put it in another process. Other than that, there is no difference
compared to standard stream output.
|> > std::ofstream message( "mailto:ka...@gabi-soft.fr" ) ;
|> > // Sends email -- under Unix, at
|> > // least, this does NOT involve
|> > // networking.
|> It doesn't? Delete the socket layer software on your unix box and
|> see how well this works.
Well, I'd have to reconfigure sendmail, but it is entirely possible to
do so. I've worked on Unix boxes which had no connection to the outside
world, nor to a LAN, and no networking support, but still supported
email. Of course, only to local users, who connected to the same
machine; it's not a configuration that anyone would use today.
But that wasn't my point. My point is that to implement this, I would
not have any networking software, at any level, in my program. Under
Unix, at least, this would map to something along the lines of:
std::ofstream message( "! /usr/bin/mail ka...@gabi-soft.fr",
std::ios::out ) ;
--
James Kanze mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Slightly off-topic... I did convince my employer that as a "heavy" user of
C++ we need to be there. I am even doing as much as I can (not much yet,
unfortunately) to contribute. See below...
[SNIP]
> Another thing that someone should probably address is getting the
> implementors to implement the standard. There's no point in
> standardizing anything if it ends up like export, or even the name
> lookup rules in templates. For the moment, I would consider getting
> implementation to conform to the current standard far more important
> than adding new features, no matter how important or useful the new
> features may be.
However this is the important part! As long as our job involves black magic
to create code which compiles on all compilers... therefore basically
invalidating all the effects of the standard... not being able to use most
or all of the "modern C++ design" I will have a very very hard time to keep
my employer convinced that it does make sense to keep participating.
Especially as the costs are very high with the meetings being on the other
side of the Earth teo times in a row...
There are very neat things added to the standard right now. I mean
discussed to be added. However as long as most of the compiler vendors are
just trying to keep up with the original standard, it makes "little or no
sense" (in a managers and his budgets point of view) to go there. If all
those nice things will take 3-5 years to be useful for us, why bother? Of
course I can say: to make sure that they *will* be useful. But then again
they can say: but hey, they did not even manage to get done what they have
agreed on in 1998? Is that standard taken seriously at all? And at that
point what can I say...? :-(
--
Attila aka WW
This communication is confidential and intended solely for the addressee(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you believe this message has been sent to you in error, please notify the sender by replying to this transmission and delete the message without disclosing it. Thank you.
E-mail including attachments is susceptible to data corruption, interruption, unauthorized amendment, tampering and viruses, and we only send and receive e-mails on the basis that we are not liable for any such corruption, interception, amendment, tampering or viruses or any consequences thereof.
[...]
> There are very neat things added to the standard right now. I mean
> discussed to be added. However as long as most of the compiler vendors
> are just trying to keep up with the original standard, it makes
> "little or no sense" (in a managers and his budgets point of view) to
> go there. If all those nice things will take 3-5 years to be useful
> for us, why bother? Of course I can say: to make sure that they *will*
> be useful. But then again they can say: but hey, they did not even
> manage to get done what they have agreed on in 1998? Is that standard
> taken seriously at all? And at that point what can I say...? :-(
Well, short sighted management is a problem. IMHO, if we can be sure
that those things will be available in 3.5 years (and judging from other
standards which "innovated", 5 years is a reasonable figure), then it is
worth the effort. But most companies don't seem to look that far in
advance.
In the case of C++, however, there is another question: will we ever see
them. The C++ standard became official five and a half years ago; for
all pratical purposes, the content was fixed, and known to be fixed, six
years ago. But not to mention export, I am still unable to find two
compilers which implement the same name lookup in templates.
IMHO, there is a very serious problem here; perhaps the most serious
problem in C++. For a long time, I pretty much ascribed it to the fact
that the standard did introduce a number of innovations, many of them
far from trivial, and it takes time for implementors to implement them
correctly. More recently, I've begun to wonder. I still think that
there was too much innovation for a first round standard, that it would
have been better to publish a simpler standard, maybe five years
earlier. But as an excuse for implementors, that one has pretty much
expired. Six and a half years is a lot of time.
And it gets worse. Given all of the confusion around template name
look-up, the wide variety of what actually happens, and above all, the
fact that until very recently, most compilers implemented the simple,
one-phase look-up of CFront, I assumed that the two phase look-up was a
recent innovation. Thanks to explinations from Gabriel Dos Reis and
David Vandervoorde, however, I am now aware that while some of the
details were still up in air, as early as 1992, it was pratically
certain that the final standard would have some form of two phase
look-up. In 1992, only CFront and Lucid had template implementations.
Borland, G++ and Zortech didn't have any support for templates, and
Microsoft didn't even have a C++ compiler. So why did all of the
compilers implement the CFront name lookup, when it was clear that this
wouldn't be the standard? Just for the fun of breaking our code when
the standard was adopted?
Seen from the outside, the obvious answer would be that the committee
failed in communicating. It's a very strange failure, however. My
principal compiler still implements templates more or less as if they
were macros. Can it be that the developers of the compiler were unaware
of the impending changes? That somehow the word didn't get out? Very
strange, considering that the lead developer of this compiler is one of
the authors of one of the 1992 paper that Gabriel Dos Reis showed me,
explaining the necessity of two phase look-up. I've heard of separation
of concerns, but this is ridiculous.
There are, of course, a number of reasons for this, and if it were just
an isolated case, I could understand it. But it is, regretfully, far
too typical. EDG implements a compiler which is fully conform (modulo
bugs, of course), and it has been available for a certain time. Why
can't others do it? Worse, why do those who use the EDG front-end turn
off the conformity?
Note that all these are real questions. There is a real problem
somewhere; I don't know what it is, and I don't know how to solve it,
but something must be done if the C++ standard is to be relevant. I've
had email exchanges with the lead developer mentionned above, and I know
that he does care -- he cares about the standard, and he cares about his
customers. But for some reason, it's not happening. And I'd like to
know why, and what we can do about it.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
But it would work in a large enough percentage of applications
to make it worthwhile, IMHO, of course.
OTOH, the Detlef method could be adapted to overcome this
limitation at the cost of more cpu time. For instance, if instead
of creating the pointer map during creation of the dummy object,
the pointer map was created during the first instantiation of a
non-dummy object, then wouldn't this avoid the problem?
More precisely,
new(detlef()) T
would set a global variable pointing to the possibly empty
pointer map and the start of T, then, during creation of each
smart_ptr, the smart_ptr CTOR would do the following:
if(start_of_T_object != 0 && T_ptr_map->not_created)
{ record my offset from start_of_T_object in T_ptr_map;
}
OOPS, that wouldn't allow any processing after the T CTOR.
But what if the auto_ptr_new described by David Abrahams in:
http://aspn.activestate.com/ASPN/Mail/Message/1521219
were used. Then the post processing, in auto_ptr_new, after the T
CTOR would reset the global variable to indicate no T was being
created; hence, all smart_ptr CTOR's checking this would not record
their offsets. Also, couldn't something similar be used to detect
whether a smart_ptr was being created in the heap or stack; hence,
whether it was a root pointer or not? The method then could be used
for classical mark-sweep.
>problem. This is a heuristic, but then, we use hash tables and
>quicksort, too, and they both depend on "luck" to work well.
I'll be giving a brand-new talk on this next week at SD West. Let me throw
in a few observations as I see them.
In my own experience, a conservative (a.k.a. guess-based) GC is adequate
for many applications. It's also no substitute for an accurate GC in
correctness or in performance. These points are pretty easy to show... in
a nutshell, conservative GCs can't guarantee that they're leak-free, and
ones that are even slightly compatible with C/C++ pointers (i.e.,
non-compacting conservative GCs) can't avoid memory fragmentation. (I'll
skip the detailed reasons for now.)
Conservative GC (a la Boehm) has a big advantage: It's the best you can do
to tack some GC onto plain vanilla C's and C++'s native heap and normal *
and &. Even then, however, such GC is not a pure conforming extension
because you have to place restrictions on pointers and references, notably
that programs can't use techniques like changing pointers' values (e.g.,
xor'ing them, which is the two-way pointer technique) or types (e.g.,
casting them to int or a char array and back). But most programs can live
with those restrictions, so they're not too onerous.
But that approach (trying to preserved * and &) doesn't extend beyond that
to the general case of garbage collection (e.g., compacting collectors
which are highly efficient). I only know two ways to add GC support to
C/C++:
- break some ISO C/C++ compatibility by putting minor restrictions on *
and & (this enables some but not all GC approaches); or
- add new abstractions that parallel * and & for a GC heap (this enables
all GC approaches including accurate and high-performance ones like
compacting collectors).
Herb
---
Herb Sutter (http://blogs.gotdotnet.com/hsutter) (www.gotw.ca)
Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Contributing editor, C/C++ Users Journal (www.gotw.ca/cuj)
Visual C++ architect, Microsoft (www.gotw.ca/microsoft)
> Conservative GC (a la Boehm) has a big advantage: It's the best you can do
> to tack some GC onto plain vanilla C's and C++'s native heap and normal *
> and &. Even then, however, such GC is not a pure conforming extension
> because you have to place restrictions on pointers and references, notably
> that programs can't use techniques like changing pointers' values (e.g.,
> xor'ing them, which is the two-way pointer technique) or types (e.g.,
> casting them to int or a char array and back). But most programs can live
> with those restrictions, so they're not too onerous.
>
> But that approach (trying to preserved * and &) doesn't extend beyond that
> to the general case of garbage collection (e.g., compacting collectors
> which are highly efficient). I only know two ways to add GC support to
> C/C++:
>
> - break some ISO C/C++ compatibility by putting minor restrictions on *
> and & (this enables some but not all GC approaches); or
>
> - add new abstractions that parallel * and & for a GC heap (this enables
> all GC approaches including accurate and high-performance ones like
> compacting collectors).
I thought I talked you out of that argument already. I don't see why
we need "new abstractions" just to enable compaction. Just a few more
restrictions on applicable techniques are required to get to
compaction, AFAICS (like that you can't use pointer values as hash
codes without extra help from the compiler). No offense intended, but
this smells to me a bit like a post-facto justification of Microsoft's
approach to GC in C++.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
I doubt it. Every GC-able type has to be default-constructible and
there must be no initialisation order dependencies (or the
constructors must conditionally perform initialisation).
(In fact the library as presented doesn't even allow you to call a
non-default constructor, though this is probably fixable.)
> OTOH, the Detlef method could be adapted to overcome this
> limitation at the cost of more cpu time. For instance, if instead
> of creating the pointer map during creation of the dummy object,
> the pointer map was created during the first instantiation of a
> non-dummy object, then wouldn't this avoid the problem?
> More precisely,
>
> new(detlef()) T
>
> would set a global variable pointing to the possibly empty
> pointer map and the start of T...
Then you lose thread-safety unless you protect every factory function
with a mutex.
<snip>
> Also, couldn't something similar be used to detect
> whether a smart_ptr was being created in the heap or stack; hence,
> whether it was a root pointer or not? The method then could be used
> for classical mark-sweep.
Then you add a large cost to construction of every pointer.
I'll admit that I was wrong to say you *need* specific compiler
support to construct the is-pointer maps, but the cost of doing it
without such support is non-trivial.
(Alternatively, my employer would be happy to sell you some 64-bit
machines to avoid the problem :-) )
There are some real measurements of programs conataining a fair amount
of "random" data in the ISMM 2000 paper by Hirzel and Diwan.
>
> >problem. This is a heuristic, but then, we use hash tables and
> >quicksort, too, and they both depend on "luck" to work well.
>
> I'll be giving a brand-new talk on this next week at SD West. Let me throw
> in a few observations as I see them.
>
> In my own experience, a conservative (a.k.a. guess-based) GC is adequate
> for many applications. It's also no substitute for an accurate GC in
> correctness or in performance. These points are pretty easy to show... in
> a nutshell, conservative GCs can't guarantee that they're leak-free, and
> ones that are even slightly compatible with C/C++ pointers (i.e.,
> non-compacting conservative GCs) can't avoid memory fragmentation. (I'll
> skip the detailed reasons for now.)
I mostly agree with the absence of guarantees, though surprisingly,
you
can actually give some space bounds. See my POPL 2002 paper. (It's
actually also quite hard to give real space bounds for type-accurate
GCs, since those can depend on compiler transformations.)
I think the significance of fragmentation in this context is generally
overrated. It can be an issue, but the cost is always bounded
(admittedly with an unpleasntly large bound) for a good
implementation, and the typical loss appears to be significantly less
than for a full copying collector. Clearly a collector that compacts
without fully copying can do better, but it's a bit tricky to do that
without time cost.
>
> Conservative GC (a la Boehm) has a big advantage: It's the best you can do
> to tack some GC onto plain vanilla C's and C++'s native heap and normal *
> and &. Even then, however, such GC is not a pure conforming extension
> because you have to place restrictions on pointers and references, notably
> that programs can't use techniques like changing pointers' values (e.g.,
> xor'ing them, which is the two-way pointer technique) or types (e.g.,
> casting them to int or a char array and back). But most programs can live
> with those restrictions, so they're not too onerous.
Whether or not the xor trick is standard conforming has been debated
repeatedly. I think the answer is unclear, since it involves casting
a pointer to a fixed size integer and back. A fully conservative GC
doesn't care much about a simple type cast; but in combination with
arithmetic on the resulting int it's an issue.
>
> But that approach (trying to preserved * and &) doesn't extend beyond that
> to the general case of garbage collection (e.g., compacting collectors
> which are highly efficient). I only know two ways to add GC support to
> C/C++:
> ...
The expected performance cost of conservative scanning in a collector
is unclear. There are certainly cases in which our collector beats
something like Sun's HotSpot collector, though that's atypical. And
there are other techniques that might help the conservative collector
where we currently lose.
I haven't been following this discussion in detail. But it seems to
me that even if you rely on a conservative collector, you want to
retain the option of having the compiler provide whatever pointer
location information it can. You can still omit the information where
it is hard to generate (e.g. top stack frame if you don't require safe
points) or impossible to provide (C unions).
Hans
> >> You understood correctly. Yet things are not as bad as one might
> >> put them. There are a lot of aspects. One is, most integers in a
> >> program are statistically small; so if the allocator arranges
> >> things such that pointers have big integral values, clashes are
> >> reduced. Second, in many systems all allocated pointers are
> >> multiples of four, which reduces chances of clash by 75% for
> >> random integers. There are many tricks like that; I remember just
> >> these, but I'm sure gc implementors has more up their sleeves.
> >Independantly of tricks, I believe that Boehm actually did some
> >statistics on real programs, and found that false addresses were
> >never a
> I doubt that Hans used that word. :-)
At least not to give the impression my words give. I was a bit sloppy
in my wording, and on rereading, the phrase seems to say more than I
meant it to. I certainly didn't mean to imply that it could never be a
problem. Only that in the cases actually tried and reported, it was
never a problem.
Note to that by problem, I mean problem. Its quite possible that some
memory was not collected. It was never enough, however, to cause a real
problem.
The solution is far from perfect, or even ideal. It is, however,
significantly better than nothing at all, and for most applications, it
is probably acceptably good. The theoretical probability of incorrectly
holding on to enough memory to cause a problem is small, and actual
tests seem to indicate that the real probability is even smaller, since
the case didn't occur in any of the reported experiments.
(Strictly speaking, I said "never were", and not "never would be":-).
But I agree that the formulation is too readily misunderstood.)
> >problem. This is a heuristic, but then, we use hash tables and
> >quicksort, too, and they both depend on "luck" to work well.
> I'll be giving a brand-new talk on this next week at SD West. Let me
> throw in a few observations as I see them.
> In my own experience, a conservative (a.k.a. guess-based) GC is
> adequate for many applications. It's also no substitute for an
> accurate GC in correctness or in performance. These points are pretty
> easy to show... in a nutshell, conservative GCs can't guarantee that
> they're leak-free, and ones that are even slightly compatible with
> C/C++ pointers (i.e., non-compacting conservative GCs) can't avoid
> memory fragmentation. (I'll skip the detailed reasons for now.)
> Conservative GC (a la Boehm) has a big advantage: It's the best you
> can do to tack some GC onto plain vanilla C's and C++'s native heap
> and normal * and &. Even then, however, such GC is not a pure
> conforming extension because you have to place restrictions on
> pointers and references, notably that programs can't use techniques
> like changing pointers' values (e.g., xor'ing them, which is the
> two-way pointer technique) or types (e.g., casting them to int or a
> char array and back). But most programs can live with those
> restrictions, so they're not too onerous.
Note that the restrictions also apply to the compiler optimizer.
Certain optimization techniques cannot be used. I don't think that this
is too relevant to current compilers, but it shouldn't be completely
forgotten.
> But that approach (trying to preserved * and &) doesn't extend beyond
> that to the general case of garbage collection (e.g., compacting
> collectors which are highly efficient). I only know two ways to add GC
> support to C/C++:
> - break some ISO C/C++ compatibility by putting minor restrictions on *
> and & (this enables some but not all GC approaches); or
> - add new abstractions that parallel * and & for a GC heap (this
> enables all GC approaches including accurate and high-performance ones
> like compacting collectors).
I'm not sure I understant what you mean here. Do you want to use
different operators when the memory is garbage collected?
In order to allow compacting garbage collection, the garbage collector
must be able to identify all pointers. I presume your statement has
something to do with this. But I'm not sure -- it would seem to me that
this would be a problem regardless of the operator being used.
--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
template
< class SubjOffYes
>
class
mk_place_new
//Purpose:
// Provide a general template with a place_new
// class method which can be specialized in
// case something other than a default CTOR
// for SubjOffYes is needed.
//
{
protected:
typedef
SubjOffYes
subj_type
;
static
subj_type*
place_new(void*p)
//Purpose:
// Allow specializations on subj_type to use
// something other than default CTOR.
{ subj_type*s = new(p) subj_type
; return s
;}
};
Then, if a non-default CTOR is needed for type, NonDef, define
the specialization, mk_place_new<NonDef>, where the
non-default CTOR is used instead of the default CTOR
in the static place_new.
>
[snip]
> > would set a global variable pointing to the possibly empty
> > pointer map and the start of T...
>
> Then you lose thread-safety unless you protect every factory function
> with a mutex.
Or unless you use thread local storage (TLS), as does the Boehm
collector, as described here:
http://www.hpl.hp.com/personal/Hans_Boehm/gc/scale.html
The would result in duplicate maps for each gc type in each TLS.
Of course during the actual garbage collection in multithreaded
environment, the thread which actually does the collection would have
to check whether it had a map, and if not, either create one
(resurrecting the non-default CTOR problem) or search each thread's
TLS for the map. I've never programmed with threads; hence, the above
could be all non-sense, but I'm guessing, based on a cursory look at
scale.html, that Hans must somehow access the TLS for all the
threads.
>
> <snip>
> > Also, couldn't something similar be used to detect
> > whether a smart_ptr was being created in the heap or stack; hence,
> > whether it was a root pointer or not? The method then could be used
> > for classical mark-sweep.
>
> Then you add a large cost to construction of every pointer.
One test of a global variable (again in TLS). If the test succeeds,
then push the pointer onto a root_stack and set a flag in the
smart_ptr indicating it's on the stack. The smart_ptr DTOR checks a
flag to see if it's on the stack, and pops's from the root_stack. All
in constant time, IIUC (of course).
>
> I'll admit that I was wrong to say you *need* specific compiler
> support to construct the is-pointer maps, but the cost of doing it
> without such support is non-trivial.
OK. I agree that the time would be non-trivial, but maybe acceptable
since, IIUC, it would be constant time (since, except for the first
time, the test for creating the map fails).
Yep, that's what we are doing, namely explicit management with
smartpointers (I'm the one who brought in the 50M example). Those 50M
blocks usually contain experimental data coming from 12 bit apparatus,
and squeezed into 8 bits, so I guess for this discussion the content
is random enough ;-)
And once we had the smartpointer mechanisms in place and working, we
have not felt any great need for separate garbage collection even for
smaller objects.
> (Alternatively, my employer would be happy to sell you some 64-bit
> machines to avoid the problem :-) )
And to all our customers :-)))
Regards
Paavo
> look-up. In 1992, only CFront and Lucid had template implementations.
> Borland, G++ and Zortech didn't have any support for templates, and
> Microsoft didn't even have a C++ compiler.
That's not true. Borland C++ 3.1 is dated midyear '92. It had tempaltes
very well. And even 3.0 had them a year before that.
I no longer have the MSC/C++ 7.0 compiler to look at its release date, but
it was out about the same time as BC3.1. It had C++, though didn;t have
templates -- in fact MS didn't put tempate support to any of its 16 bit
dos/win compilers.
> So why did all of the
> compilers implement the CFront name lookup, when it was clear that this
> wouldn't be the standard? Just for the fun of breaking our code when
> the standard was adopted?
As I saw it compilers followed CFront or the ARM. And what will go to the
standard seemed pretty moot.
> Seen from the outside, the obvious answer would be that the committee
> failed in communicating.
IMHO you're in a pretty big company with thinking 2pl is some new feature
dropped in late. Though the discussion clearly appears in D&E.
Also I think the committee made a poor job on this issue. By the time the
standard got finalised template usage was pretty common, and they should
have been aware of the tons of code changing the way used by masses (iow:
everyone) by accepting that.
I guess export could be their motivation, which asks for early compile and
lookup.
> It's a very strange failure, however. My
> principal compiler still implements templates more or less as if they
> were macros. Can it be that the developers of the compiler were unaware
> of the impending changes?
I think it's quite possible. Also they coud thnk practically -- that
standard will refreain from breaking the existing ways and thinking.
Bjarne have some points on why early binding may be good, but they didn't
convince me. It tkaes away a big amount of flexibility, while saves nothing
in practical terms -- where picking up some strange and unwanted function is
an issue there are bigger problems with or without templates. Also it's not
at all intuitive. Not natural. While the macro approah is pretty
straightforward.
> That somehow the word didn't get out? Very
> strange, considering that the lead developer of this compiler is one of
> the authors of one of the 1992 paper that Gabriel Dos Reis showed me,
> explaining the necessity of two phase look-up. I've heard of separation
> of concerns, but this is ridiculous.
But it;s a necessity only to have export, isnt't it? Do we pay a high price
to make something implementabe that no one appears to implement, and almost
nobody couldn't live without?
> There are, of course, a number of reasons for this, and if it were just
> an isolated case, I could understand it. But it is, regretfully, far
> too typical. EDG implements a compiler which is fully conform (modulo
> bugs, of course), and it has been available for a certain time. Why
> can't others do it? Worse, why do those who use the EDG front-end turn
> off the conformity?
Likely they do use templates and want them work like they worked before.
rewriting well-working stuff just to make it compile on the new compiler is
not really profitable. Even if there's no need to change the code, just
move all the declarations above tempaltes may create a hell, or a
practically unsolvable situation. Especially not having the ability to
forward-declare typedefs. [I mean: adding declarartions with class foo --
when foo as defined turns out a typedef, not a class. A typedef to a
template more and more often.]
> Note that all these are real questions. There is a real problem
> somewhere; I don't know what it is, and I don't know how to solve it,
> but something must be done if the C++ standard is to be relevant.
Well, the easiest soultuion would be to standardise the existing practice:
scrap the 2pl and export right away, before a code base depending on them
could build up. [Do I hear "fat chance"? ;-]
> I've
> had email exchanges with the lead developer mentionned above, and I know
> that he does care -- he cares about the standard, and he cares about his
> customers. But for some reason, it's not happening. And I'd like to
> know why, and what we can do about it.
First step as always: admit that it IS a problem.
Second step to allocate the *will* to solve it.
The rest is generally easy. IMHO we have a finite set of compiler
developers. Why not collect them (if not physically then on some list of
newsgroup) to tell their reasons not to implement the thing in question.
I don't believe they are all just lazy or ignorant, or want to harm others.
And the sum of reasons will speak for itself.
And if the standard is there to serve the interest of compiler writesr and
the language users -- and not the other way around, some solution could be
found.
Paul
As for all this, a little comment. The second step is usually missing.
What my point is that it *is* possible to get onto the committee and make
oneself heard. But unfortunately it does not happen. I mean that if
someone thinks that the committee does not do a good job, please "allocate
the will" and come there and help with the work. There are ways to
contribute.
--
Attila aka WW
Just a short reaction. The _main_ reason I hear from implementors for _not_
including a standard feature or not doing things in a standard way is:
binary compatibility as well as their _customers_ shouting each time there
is a change in the language. The trouble is that we have "wo kinds" of C++
users. One is who knows it is inevitable that compilers will change and a
standard to be adopted, and therefore does not try to "keep the industry
back". (Wording is too harsh, basically this is how the other side sees
it.) And there is the other group, who wants to get closer to the standard,
they refactor, they use the new techniques and factor them into the code if
it makes it more simple, they need to be portable etc. etc.
What I mean is that there are people who refuse to move away from the ARM
compiler they have. And I am talking about today. They have their reasons
(stability? etc.). We have our own. Which view will win? The one which
brings more business (money) to the compiler implementors... If you say to
a (traditional) implementor that you want standard feature X and you want it
the right way or otherwise you will bring your millions of USD/EUR somewhere
else, they will do it. :-) I have no idea how that works with gcc, I mean
if you can just go in and add the standard features you need?
--
Attila aka WW