Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-06 Thread Dave Abrahams
On Thursday, February 06, 2003 3:13 PM [GMT+1=CET],
David B. Held [EMAIL PROTECTED] wrote:

 David B. Held [EMAIL PROTECTED] wrote in message
 b1m57m$702$[EMAIL PROTECTED]">news:b1m57m$702$[EMAIL PROTECTED]...
[...]
I mean, the optimally_inherit eliminates the empty bases, and
yet there is size bloat.  So VC++ makes the class bigger for
some other reason than that it has empty bases.  I will try to
write some tests to see why that is, or at least how.
  
   I repeat, I bet it's MI-related.
 
  The proof of the pudding is in the eating.

 I got a chance to taste the pudding, the the results are inconclusive.
 The cause of the size bloat was that I had changed ref_counted to
 inherit from noncopyable.  Seems like an innocent enough change.
 Seems that for the single-inheritance case, we should see some
 EBO action, right?  Well, we do, unless ref_counted is a base in
 an MI hierarchy.  Why its place in an hierarchy should change its
 size is a mystery to me,

What do you mean that its *place* in the hierarchy affects the size? If it's
in the hierarchy, it's a base.

 but taking out noncopyable restores that
 magical size.  Now, I would appreciate it if people with Intel, CW,
 and some other compilers would try out the code in the sandbox
 and see if the first test passes (turn on --log-level=all, and pipe the
 output to your favorite paginator).

BTW, these are not the kind of tests I was thinking of.  I was more
interested in simple tests with SI and MI using dummy classes with zero or
more data members and trivial/non-trivial ctors/dtors.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-06 Thread Dave Abrahams
From: David B. Held [EMAIL PROTECTED]

 Dave Abrahams [EMAIL PROTECTED] wrote in message
 008c01c2ce1f$87ca8620$6501a8c0@penguin">news:008c01c2ce1f$87ca8620$6501a8c0@penguin...
  [...]
  What do you mean that its *place* in the hierarchy affects the size? If
  it's in the hierarchy, it's a base.

Sorry, I thought that it is noncopyable, not ref_counted.

 But if it's not in the smart_ptr hierarchy, it's not a base.  So if it's
not
 a base, it's at the top (or bottom) of the hierarchy, with noncopyable as
a
 base.  And that's my point.  Being a base changes its size.

No, it doesn't.  It can't.  sizeof(ref_counted) is the same no matter where
you measure it.  What changes is the size that gets contributed to its
derived class.

It's clear to me why that could happen.  It could be just a simple-minded
rule to avoid violating the standard requirements, which are written so that
no two objects of the same type can have the same address.  The rule would
be, if I applied the EBO on this type, add some padding after it in an MI
context so that other bases of the same type can't end up overlapping with
it.  It's a dumb rule, since it's easy enough to lay out empty bases in the
single-inheritance case at the beginning of the object, and since all types
have size  0, you don't need to do anything other than not optimize in
the MI case.

  BTW, these are not the kind of tests I was thinking of.  I was more
  interested in simple tests with SI and MI using dummy classes with
  zero or more data members and trivial/non-trivial ctors/dtors.

 Yes, like what Jason Shirk did.  It's just that I did a diff of the
version
 that was the right size and the one that wasn't, and saw that change,
 so I wanted to test it right away.  The weird thing is, the storage policy
 also has an empty base for the policy adaptor, and yet, it doesn't
 seem to affect the size of smart_ptr.  Go figure.  But like Jason also
 pointed out, the order of bases makes a difference, so maybe the
 fact that storage_policy comes first affects the size.  I noticed that
 this is actually the case on bcc, and I suspect, on most compilers.

 Anyway, non-copyable doesn't really convey the right concept
 anyway, since ref_counted defines copy c'tors!  I just wanted to hide
 the assignment operator, and doing that manually works fine.

I'm interested in what happens when either of ownership or storage are
themselves empty.  And, of course, the independent tests not based on
smart_ptr.

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-03 Thread David Abrahams
David B. Held [EMAIL PROTECTED] writes:

 David Abrahams [EMAIL PROTECTED] wrote in message
 [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
 [...]
 The problem arises if the user passes an empty policy class with
 non-trivial ctor or dtor: then the fact that it's being
 constructed/destructed at different times from the rest of the bases
 will have visible effects.

 Ok, now I see the problem, and one conceivable scenario for this is
 an intrusive ownership policy.  It would most likely be empty, yet the
 cleanup would occur in the d'tor under my latest model, so that it has
 proper exception safety.  Ouch.  On the other hand, I just saw a
 reference to Josuttis  Vandevoorde that I recalled reading whereby
 they refer to a BaseAndMember idiom in which they aggregate the
 non-empty parameter and derive from the emtpy one, relying on
 EBO to give optimal size.  

That's called boost::compressed_pair.

 Once again, I might be able to reverse the logic and aggregate the
 empty member and derive from the non- empty one.  I guess that
 depends on how well VC++  friends perform empty member
 optimization.

There is no such thing as empty member optimization.

 That's true, but we're no longer talking about EBO failure.  Even after
 the empty bases have been eliminated, we still get bloating.  So it's
 just random size adjustment.  But you're right that some testing might
 increase the confidence that the size won't go up.

I bet you it's not random, but associated with MI.

 [...]
  It would be nice to have some assurance that this won't happen,
  but the current state of affairs with the MI setup doesn't exactly
  involve EBO

 I don't know what you mean by that.

 I mean, the optimally_inherit eliminates the empty bases, and yet
 there is size bloat.  So VC++ makes the class bigger for some other
 reason than that it has empty bases.  I will try to write some tests to
 see why that is, or at least how.

I repeat, I bet it's MI-related.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



RE: [boost] Re: SmartPtr - Exception safety reprise

2003-02-02 Thread Jason Shirk
 -Original Message-
 From: David Abrahams [mailto:[EMAIL PROTECTED]]
 
 David B. Held [EMAIL PROTECTED] writes:
 
  Well, I want to at least give the VC++ guys a few days to see if
  they say anything.  I posted a question on a M$ newsgroup.  I
  think I did the first time around, too, and they didn't.  It would
be
  really cool if, say, Jason Shirk offered some insight, or at least
  knocked some skulls so we got *some* kind of answer, even if
  it's there's no way in heck we will give out that kind of
  information.
 

If you aren't getting reasonably prompt responses to questions like this
on MS newsgroups, send me a private email and I'll definitely follow up.
As a team, VC++ is significantly more responsive to NG posts now, but
some still slip through the cracks.

 What question are you asking?  I think all NDAs on the vc7.1 betas are
 expired, so I can just run a test...
 
 However, you obviously missed my point: there _is_ no way in heck
 they're going to change the object layout, thus making vc7.1 object
 code incompatible with vc7 object code.  Objects with multiple empty
 bases have to have the same size in both versions and their members
 have to live at the same offsets.
 
 BTW, VC++ is not the only kid on the block, and the same argument
 applies to all the other players.
 

As usual, you are absolutely correct.  Backwards compatibility in our
object model is critical.  I seriously doubt we'll ever do the ZBO by
default.

I do plan on implementing it in the next few months, and it will
definitely be under a switch.  I can't possibly predict when anyone
outside MS will see such a compiler though, sorry.

--
Jason Shirk
VC++ Compiler Team
___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-01 Thread David Abrahams
David B. Held [EMAIL PROTECTED] writes:

 Well, I want to at least give the VC++ guys a few days to see if
 they say anything.  I posted a question on a M$ newsgroup.  I
 think I did the first time around, too, and they didn't.  It would be
 really cool if, say, Jason Shirk offered some insight, or at least
 knocked some skulls so we got *some* kind of answer, even if
 it's there's no way in heck we will give out that kind of
 information.  

What question are you asking?  I think all NDAs on the vc7.1 betas are
expired, so I can just run a test...

However, you obviously missed my point: there _is_ no way in heck
they're going to change the object layout, thus making vc7.1 object
code incompatible with vc7 object code.  Objects with multiple empty
bases have to have the same size in both versions and their members
have to live at the same offsets.

BTW, VC++ is not the only kid on the block, and the same argument
applies to all the other players.

 At least then I could give up hope, and we could fully enter the
 tedious debate over alternatives.  But there must be *someone* on
 the VC++ compiler team that wrote the EBO code, and if it were me,
 I'd have enough pride to at least say when I know that it *does*
 work (and it does work for some MI...optimally_inherit was doing its
 job until the latest round of changes).  

What is optimally_inherit?  Latest round of changes in what?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-01 Thread David Abrahams
David B. Held [EMAIL PROTECTED] writes:

 David Abrahams [EMAIL PROTECTED] wrote in message
 [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
 [...]
   C) Make sure the first base class of smart_ptr is the one that
  manages destruction of its resources:

snip

 I was actually thinking in this direction somewhat.  

Then you're getting the hang of this EH stuff; congratulations!

 I did notice that it really is the smart_ptr d'tor that really knows
 how to properly clean stuff up, and it should probably be the one to
 do so.

But coordinating cleanup in the smart_ptr dtor was causing the problem
you cited in the first place!  In my version it's the ptr_manager base
class that coordinates the cleanup by encapsulating ownership and
storage.

-Dave

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-01 Thread David Abrahams
David B. Held [EMAIL PROTECTED] writes:

 David Abrahams [EMAIL PROTECTED] wrote in message
 [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
 [...]
 What question are you asking?  I think all NDAs on the vc7.1 betas
 are expired, so I can just run a test...

 Actually, I wanted someone on the compiler team to give me a set of
 circumstances under which EBO is guaranteed to work.  If there is no
 way to get MI to fit into those circumstances, then we can give up.

 [...]
 BTW, VC++ is not the only kid on the block, and the same
 argument applies to all the other players.

 Yes, but you seem to imply that other Win32 compilers try to be
 object-compatible with VC++

Up to a point.  I know MWerks is object-compatible in the
single-inheritance case (for the sake of COM and MFC), but not if
there's MI.  However, they still have MI EBO problem.

Further, this is not a Win32-specific problem.  Most Unix compilers
that aren't GCC-3.x have it as well, AFAICT.

 so it seems they should exhibit the same behaviour.
 
 If there is some way to get the desired optimization,
 with any luck, the other compilers will perform it as well.  Or maybe
 this is wishful thinking?

It is in the case of MWerks, anyway.

 [...]
 What is optimally_inherit?  Latest round of changes in what?

 Optimally_inherit is a device that is the dual of compressed_pair.
 Andrei suggested it when this issue first came up.  Whilst
 compressed_pair aggregates when a type is non-empty, and
 inherits when it's empty, optimally_inherit inherits when the type
 is non-empty, and just calls c'tors on temporaries when the type is
 empty. This way, empty bases don't actually enter the inheritance
 tree.  

I guess that's OK if you don't care how many ctors and dtors get
called.  The lifetimes of these temporaries obviously won't mirror
that of the smart_ptr.  Sounds like a fragile arrangement to me.

 Unfortunately, EBO interacts with non-empty bases as well as empty
 ones, and that is our problem.

If you only inherit from non-empty bases, how is EBO relevant at all?

 The latest round of changes is the set of changes that moves
 cleanup from named procedures (destroy(), release(), etc.) to d'tors.
 For this reason, I suspected that non-trivial user-defined d'tors were
 causing VC++ to drop EBO.  But commenting out the d'tors just to
 check the size did not restore EBO.  So now I would like a VC++
 compiler team member (preferably the one(s) who wrote the EBO
 code) to tell me when EBO works, and when it doesn't, or as much
 about that as possible.  The optimally_inherit trick works just fine
 on BCB, and gcc didn't need it to begin with (that big stud of a
 compiler!).  If we can get VC++ and VC++ wannabes to invoke
 EBO again, we can at least cover a good amount of the market, no?

Yes.

 I know that optimally_inherit *does* work under VC++ for some cases.
 I just don't know exactly what those cases are, and I don't really
 want to spend a week trying to discover it, especially as that won't
 help people who are writing custom policies.

Why not?

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost



Re: [boost] Re: SmartPtr - Exception safety reprise

2003-02-01 Thread David Abrahams
David B. Held [EMAIL PROTECTED] writes:

 David Abrahams [EMAIL PROTECTED] wrote in message
 [EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
 [...]
 Up to a point.  I know MWerks is object-compatible in the
 single-inheritance case (for the sake of COM and MFC), but not
 if there's MI.  However, they still have MI EBO problem.

 Further, this is not a Win32-specific problem.  Most Unix compilers
 that aren't GCC-3.x have it as well, AFAICT.

 So in your opinion, *ought* the optimally_inherit solution to work
 even on these compilers?

If you don't care about ctors and dtors, it sounds plausible, but
there's no reason in principle that they shouldn't have the same
problems you cite below for VC++.  You never know with some of them,
though.  Borland is particularly strange about layout.

 [...]
 I guess that's OK if you don't care how many ctors and dtors get
 called.  The lifetimes of these temporaries obviously won't mirror
 that of the smart_ptr.  Sounds like a fragile arrangement to me.

 I imagine that the temporaries won't get created at all, 

Whaaa?  A temporary that never gets created?

 since their sole purpose is to verify policy compatibility.  In the
 majority of cases, they will simply call an appropriate copy c'tor,
 which will be trivial or generated, because the class has no state.

Maybe you should illustrate what you mean, 'cause I'm lost.

 If you only inherit from non-empty bases, how is EBO relevant at
 all?

 That's a very good question.  Maybe I should call it an Empty
 Derived Optimization problem.  For some reason, even in this
 configuration, VC++ insists that sizeof(smart_ptr)  8:

 class smart_ptr
 : optimally_inherit
 optimally_inheritstorage, checking,
 optimally_inheritownership, conversion
 
 { ... }

Since I can't see what's in the bases nor any of smart_ptr's data
members here, it's hard to know how to interpret sizeof(smart_ptr)  8
or whether it's even a problem [but I get it below].

 I can prove that optimally_inheritstorage, checking only derives
 from storage, and similarly for ownership with a simple test case.
 So why VC++ thinks it needs to inflate the size of smart_ptr is
 beyond me.  But it isn't just smart_ptr.  It inflates the size of the top-
 level optimally_inherit, which is inheriting from two non-empty base
 classes.  Perhaps we should call it the Non-emtpy Base MI
 Pessimization (NoBMIP)?  

OK, I get the picture now.

 I assumed it was because it didn't want any of the bases to share an
 address with the derived class, which is analogous to the EBO case.
 But perhaps I misunderstand what is going on, and you can shed some
 light on it for me.

I don't think I can do any better than you.  I have the same tools at
my disposal.  I'd do a bunch of experiments and look at the resulting
class layouts by checking the size and the relative addresses of
members.

 [...]
  I know that optimally_inherit *does* work under VC++ for some
  cases.  I just don't know exactly what those cases are, and I don't
  really want to spend a week trying to discover it, especially as that
  won't help people who are writing custom policies.

 Why not?

 Well, suppose that I discover *some* configuration in which EBO and
 optimally_inherit produce the desired size, but I don't know *why*
 that configuration has the desired result.  How is a user to know if
 his custom policy is going to kill EBO again or not, based on the
 working configuration?

You could probably figure out the VC++ algorithm by experimentation,
but that still wouldn't help a user trying to write portable,
efficient code, unless you find a workaround for every other compiler.

-- 
   David Abrahams
   [EMAIL PROTECTED] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

___
Unsubscribe  other changes: http://lists.boost.org/mailman/listinfo.cgi/boost