[optional] layout

View: New views
11 Messages — Rating Filter:   Alert me  

[optional] layout

by Domagoj Saric :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


why is boost::optional laid out so that the bool comes before the object's
placeholder/storage?

this takes up to 7 extra bytes of storage with default alignement and, more
importantly, it forces pointer offset adjustment/calculation when accessing
a boost::optional<> through a pointer (and trying to access the actual
contained object)...
it also makes life harder for those of us keen to hackery ;) because it
makes the address of an optional different from the address of the actual
object within the optional...


ps. it would be 'cool' if all of the functionality from boost::optional<>
not related to the 'is initialized' bool (conditional destruction, etc...)
could be extracted into a separate class (usefull for cases where you have
to delay/in-place construct an object but are certain that you will
construct it by the point where it needs to be used or destroyed...so you do
not need the 'conditional' overhead)...

--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley




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

Re: [optional] layout

by Steven Watanabe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AMDG

Domagoj Saric wrote:
> why is boost::optional laid out so that the bool comes before the object's
> placeholder/storage?
>
> this takes up to 7 extra bytes of storage with default alignement

These two structs should both take up 16 bytes.
You don't save anything by reordering the
members.

struct s1 {
    bool initialized;
    double value;
};

struct s2 {
    double value;
    bool initialized;
};

>  and, more
> importantly, it forces pointer offset adjustment/calculation when accessing
> a boost::optional<> through a pointer (and trying to access the actual
> contained object)...
>  

Is the difference in performance actually measurable in any way?

> it also makes life harder for those of us keen to hackery ;) because it
> makes the address of an optional different from the address of the actual
> object within the optional...
>  

Um, you shouldn't rely on this anyway.  The standard only
makes guarantees about the addresses of sub-objects for
POD types.

> ps. it would be 'cool' if all of the functionality from boost::optional<>
> not related to the 'is initialized' bool (conditional destruction, etc...)
> could be extracted into a separate class (usefull for cases where you have
> to delay/in-place construct an object but are certain that you will
> construct it by the point where it needs to be used or destroyed...so you do
> not need the 'conditional' overhead)...
>  

In Christ,
Steven Watanabe

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

Re: [optional] layout

by Domagoj Saric :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


"Steven Watanabe" <watanabesj@...> wrote in message
news:4AC4EDDE.5070606@......

> These two structs should both take up 16 bytes.
> You don't save anything by reordering the
> members.

true :blush: should've checked the issue beforehand ;)
but it was more of a side note/'thought' anyway...my main concern was with
following issue...

>>  and, more importantly, it forces pointer offset adjustment/calculation
>> when accessing a boost::optional<> through a pointer (and trying to
>> access the actual contained object)...
>>
>
> Is the difference in performance actually measurable in any way?

well, "actually measurable difference in performance" is, imho, kind of a
"grey area"/"subjective metric"...and a library should not, imnho, make
'real world' usage assumptions if it does not have to...and in this case, as
far as i can see/imho, it does not have to...that is, from the standpoint of
boost::optional<> it makes no difference what layout it uses, but one of
those layouts does cause the usage of more complicated addresing modes/extra
adjustment code (depending on the platform) in certain cases...the fact that
this is infinitesimally insignificant compared to a single default
construction of a std::sstream ;-D makes no difference (if i am not mistaken
with the assumption that the actual layout makes no difference from the
boost::optional<> point of view)...


--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley



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

Re: [optional] layout

by Mathias Gaunard-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Domagoj Saric a écrit :

> ps. it would be 'cool' if all of the functionality from boost::optional<>
> not related to the 'is initialized' bool (conditional destruction, etc...)
> could be extracted into a separate class (usefull for cases where you have
> to delay/in-place construct an object but are certain that you will
> construct it by the point where it needs to be used or destroyed...so you do
> not need the 'conditional' overhead)...


If you are sure that the optional gets initialized, then there is no
point in such a thing to begin with.

Simply don't declare your object before you can initialize it. If you
can't, that probably means you need to reorganize your code.

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

Re: [optional] layout

by Domagoj Saric-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

"Mathias Gaunard" <mathias.gaunard@...> wrote in message
news:ha5309$6jc$1@......
Domagoj Saric a écrit :

>> ps. it would be 'cool' if all of the functionality from boost::optional<>
>> not related to the 'is initialized' bool (conditional destruction, etc...)
>> could be extracted into a separate class (usefull for cases where you have
>> to delay/in-place construct an object but are certain that you will
>> construct it by the point where it needs to be used or destroyed...so you do
>> not need the 'conditional' overhead)...
>
>
>If you are sure that the optional gets initialized, then there is no point in
>such a thing to begin with.
>
>Simply don't declare your object before you can initialize it. If you can't,
>that probably means you need to reorganize your code.
that's true for 'most' code but not all...otherwise placement new would be
equally 'pointless'/indication of bad design/code organization...
...because that is what i was whishing for to be extracted from optional<> -
the placement new/in-place construction + aligned storage + reference
workarounds&co. wrapped up machinery...

...for example:
1.
template <class Data, class Widget>
class DataWithUI : public Data
{
  void createUI();
  void destroyUI();
  boost::optional<Widget> ui;
}

where ui is always created after data and always destroyed before data...and
there are many such pairs...if all uis are created and destroyed at the same
time (for example with/by their parent) there is no need to track their
lifetime individually hence no need for the individual bools for each
"optional" ui...

2. you have fusion containers of non default constructible objects and/or
objects that you cannot construct all at once (a trivial example: one of the
parameters to the constructor of the objects is the order/index of the object
in the fusion container) but need to, for example, construct them in a
loop...so you wrap that fusion container and ensure proper
construction/initialization and complete destruction in the
constructor/destructor of the wrapper - this then gives you single
deterministic points of construction and destruction (for all the contained
objects) making the individual bools redundant...


3. the simple bool/true-false lifetime management is not enough for a
situation, e.g. you have a  reference counted singleton...then the following
source code:
...
boost::optional<Singleton> singleton;
...
if ( !ref_count++ )
  singleton = boost::in_place();

will actually produce the following binary code
if ( !ref_count++ )
{
  if ( singleton.is_initialized() )
    ~singleton();
  singleton = boost::in_place();
}

with similar redundancy in the destructor...



--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley





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

Re: [optional] layout

by Domagoj Saric-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

"Steven Watanabe" <watanabesj@...> wrote in message
news:4AC4EDDE.5070606@......
>> it also makes life harder for those of us keen to hackery ;) because it
>> makes the address of an optional different from the address of the actual
>> object within the optional...
>>
>
> Um, you shouldn't rely on this anyway.  The standard only
> makes guarantees about the addresses of sub-objects for
> POD types.

and, if i'm not mistaken, for class sub-objects that belong to the same "access
section"...although, yes, the point is still moot from a standard-pure POV as
boost::optional<> is free to use base classes for implementation and it in fact
does...

--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley




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

Re: [optional] layout

by Gottlob Frege :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Oct 27, 2009 at 7:13 PM, Domagoj Saric <dsaritz@...> wrote:
> ...because that is what i was whishing for to be extracted from optional<> -
> the placement new/in-place construction + aligned storage + reference
> workarounds&co. wrapped up machinery...
>
> ...for example:
> 1....
> 2....
> 3....

4. An in-place fast pimpl.  see Herb Sutter's
http://www.gotw.ca/gotw/028.htm for why not to do this.  Yet I've done
it anyhow.  I templatized it and it probably turns out to be the same
as most of the internals of optional<>.  I also managed to mitigate
most of the list of his concerns for why not to do this.  Still not
something to do without good reason, but manageable.

eg:

// just forward declare CRITICAL_SECTION,
// instead of including <windows.h>
// and polluting everything with its macros:

struct CRITICAL_SECTION;

class CriticalSection // windows version of cross-platform CS
{
   in_place_pimpl<CRITICAL_SECTION, 16> pCS;  // 16 is sizeof(CRITICAL_SECTION)
   //...
};

In the cpp file for CriticalSection, we check that sizeof(pCS) really
is 16, properly aligned, etc.
The in_place_pimpl<> also forwards constructor args, implements operator=, etc.

But it is not just for in_place_pimpl, it is for any time you need
finer control over construction/destruction/storage.  In fact, each of
those is a policy to the underlying reinterpret_bytes<> or whatever I
called it.

I probably should have looked at the internals of optional<>, would
have made my life easier...


Tony
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [optional] layout

by Stefan Strasser-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Am Wednesday 28 October 2009 15:31:55 schrieb Gottlob Frege:

> On Tue, Oct 27, 2009 at 7:13 PM, Domagoj Saric <dsaritz@...> wrote:
> > ...because that is what i was whishing for to be extracted from
> > optional<> - the placement new/in-place construction + aligned storage +
> > reference workarounds&co. wrapped up machinery...
> >
> > ...for example:
> > 1....
> > 2....
> > 3....
>
> 4. An in-place fast pimpl.  see Herb Sutter's
> http://www.gotw.ca/gotw/028.htm for why not to do this.

that is not the same thing as gottlob was proposing. boost::optional<> doesn't
have the problems herb sutter lists, and a type that is only used for in
place construction, without optional's conditional bool, wouldn't either.

I've been missing such a type, too, but I think it should be part of the boost
in place utility instead of boost::optional:
http://www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html

see "container-side usage" there.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [optional] layout

by Gottlob Frege :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> that is not the same thing as gottlob was proposing.

What Domagoj was asking for was:
...because that is what i was whishing for to be extracted from optional<> -
the placement new/in-place construction + aligned storage + reference
workarounds&co. wrapped up machinery...

with examples of uses.  I gave another example of where those
internals could be useful, and what I ended up doing.

> boost::optional<> doesn't
> have the problems herb sutter lists, and a type that is only used for in
> place construction, without optional's conditional bool, wouldn't either.
>

agreed.  I was off on a tangent about just my example.

> I've been missing such a type, too, but I think it should be part of the boost
> in place utility instead of boost::optional:
> http://www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html
>
> see "container-side usage" there.

Yes, in-place is again similar.  At least it handles the construction
issues.  I see it as either my templates have 10 overloads, or I use
in_place (easier for me) and make my users use it as well (bit harder
for them).  For a fast_impl, the user is probably another library
writer, already doing forwarding, so I don't see that as a problem.

Definitely lots of code doing similar things - more reasons why it
could maybe be split up / reorganized / grouped / etc.

Of course, C++0x vararg templates + 'perfect forwarding' would make
things easier and change much of this.

Tony
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: [optional] layout

by Mathias Gaunard-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Domagoj Saric wrote:

> ...for example:
> 1.
> template <class Data, class Widget>
> class DataWithUI : public Data
> {
>   void createUI();
>   void destroyUI();
>   boost::optional<Widget> ui;
> }
>
> where ui is always created after data and always destroyed before data...and
> there are many such pairs...

Make createUI the constructor and destroyUI the destructor.


 > if all uis are created and destroyed at the same
 > time (for example with/by their parent) there is no need to track their
 > lifetime individually hence no need for the individual bools for each
 > "optional" ui...

That's a good point. You initialize things in groups so you don't need a
boolean per thing.
The solution is easy: instead of a structure of optional things, make an
optional structure of things; you transform N booleans into one, as
expected.


> 2. you have fusion containers of non default constructible objects and/or
> objects that you cannot construct all at once (a trivial example: one of the
> parameters to the constructor of the objects is the order/index of the object
> in the fusion container)

You know what position a tuple element is going to be in before
initializing the tuple, surely.


> but need to, for example, construct them in a
> loop...so you wrap that fusion container and ensure proper
> construction/initialization and complete destruction in the
> constructor/destructor of the wrapper - this then gives you single
> deterministic points of construction and destruction (for all the contained
> objects) making the individual bools redundant...

Well, first, I don't think this is so easy. Are you taking into account
that constructing the subsequent elements might throw, and that you
therefore need to destruct the previous ones?

Otherwise, I don't understand that point, since tuples and loops aren't
exactly things that go well together.

Maybe you meant something else than tuples when you were talking of
fusion containers?


> 3. the simple bool/true-false lifetime management is not enough for a
> situation, e.g. you have a  reference counted singleton...then the following
> source code:
> ...
> boost::optional<Singleton> singleton;
> ...
> if ( !ref_count++ )
>   singleton = boost::in_place();
>
> will actually produce the following binary code
> if ( !ref_count++ )
> {
>   if ( singleton.is_initialized() )
>     ~singleton();
>   singleton = boost::in_place();
> }
>
> with similar redundancy in the destructor...

shared_ptr already provides delayed construction, I don't see why you
would want to use optional here?
Because you want to store the memory in static memory maybe? For that,
just use boost::aligned_storage and placement new, works with shared_ptr
like the rest just fine.

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

Re: [optional] layout

by Domagoj Saric-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

"Mathias Gaunard" <mathias.gaunard@...> wrote in message
news:hca1im$v6k$1@......
> shared_ptr already provides delayed construction, I don't see why you would
> want to use optional here?
> Because you want to store the memory in static memory maybe? For that, just
> use boost::aligned_storage and placement new, works with shared_ptr like the
> rest just fine.

sorry..i'll respond only to this last point (for the sake of a clearer
discussion) because it actually contains the main issue (my code 'wish')...
...yes :) aligned_storage and placement new (plus the few additional
workarounds for 'quirky' cases) are exactly/all i want...but because it is a
relatively often used idiom i would like not to have to write it all manually
every time...but rather have small class that wraps it up and allows me to call
construct() and destruct() (with boost::in_place support and even the 'bool'
left in debug builds for asserting correct usage)...


--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley




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