|
Boost Users : |
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2006-06-14 17:04:24
>
> From: Howard Hinnant <hinnant_at_[hidden]>
> >> On Jun 14, 2006, at 6:55 AM, David Abrahams wrote:
> >>
> >>> I think what the OP is looking for is called boost::shared_ptr ;-)
> >>
Actually, *one* of my uses is a bit more devious - more like the
short-string optimization - you might want to call it "embedded_ptr<T,
size>". Where it reserves enough space for T (because you explicitly supply
the size) and acts like a pointer to T otherwise. You might call it a hack
and/or dangerous, and I won't entirely disagree. It does have a static
assert on the implementation side (where T is known) to ensure size ==
sizeof(T), but it is still dangerous if the client compiles with different
settings than the implementation. However, knowing these caveats, it may
still be useful in cases where you really want/need to avoid the allocation
overhead (and still want to separate implementation from interface).
If that use-case is not 'worthy' enough to be an argument for
default-alignment-based-on-size, a more typical case would probably be a
custom allocator. In particular, a small-block allocator. If I need to
allocate 4 bytes, I don't want to allocate it on a 16 byte boundary. Now
maybe if I am writing an allocator am doing platform-dependent things
anyhow, but I don't necessarily think so.
Another use of aligned_storage (where T IS complete) is a more noble cause -
handling thread safe static locals:
void func()
{
static thread_safe_static_local<Foo> foo; // foo's constructor called
once, THREADSAFELY
...
}
Not sure why I bother to mention that, other than the fact it shares much of
the same code as the embedded_ptr.
P.S. even if some of you have to hold your nose when thinking of the hack
that is embedded_ptr, what do people think of the name? I've been throwing
around some different names (ie embedded_incomplete) but until Dave
mentioned shared_ptr, I hadn't thought of embedded_ptr.
>> shared_ptr can't compete with this application performance-wise.
> >
> > Well, it depends how expensive it is to copy your small object. If it
> > turns out that T is a vector, and it fits in your local buffer, when
> > Container is copied it might be a lot cheaper to use shared_ptr.
>
> Sure. I'm responding to the assertion that you need a known complete
> type to effectively use aligned_storage. My point is that there
> exist valuable use cases where this assertion is false. The
> existence of these cases is what makes the defaulted alignment
> template parameter on aligned_storage valuable.
>
> Tony's observation is that this default value is even more valuable
> if it is dependent upon the buffer size, which again I fully agree
> with. If you want a 5 byte buffer that is aligned to the "most
> stringent alignment requirements" (definition found in 5.3.4p10), an
> alignment of 16 (for example) is likely to be correct but overkill.
> I had personally settled on 8 for this particular example but Tony
> makes a convincing argument for 4 being the optimum (all numbers
> assuming current popular desktop processors and quoted just for
> example).
Actually, after thinking about it a bit, I'm now tempted to say a 5 byte
buffer should have 1 byte alignment.
eg (given a typical platform):
struct test_alignment
{
int x;
char y;
};
At first, I thought that any 5 byte structure could have AT MOST a 4 byte
alignment requirement because it could have an int as the first param, as in
the example above. However, if it does have 4 byte alignment, its size will
be 8, so that an array of them will align to 4 bytes. (Howard, you hinted at
this in another email thread).
So,
If sizeof(test_alignment) == 5, then the alignment must really be 1 (ie
there is probably a pragma pack(1) in play).
Either way, the alignment is NOT 16 (or whatever max alignment might be),
but derivable from the size of the structure.
Also, in any case, for boost::type_with_alignment<5> doesn't compile. I
think it should at least do something (or else the standard/docs need to
have lots of wording explaining which ints work and which do not).
Similarly, aligned_storage has the same 'problem' and basically only works
with alignment_of (or something that does the same thing). Since that is
the case anyhow, I would suggest that aligned_storage be replaced with:
storage_for<T, count = 1>;
(which can be written in terms of aligned_storage and alignment_of, but
since the two are tied together, and typically used together, why not just
supply what is really wanted).
So really I'd like:
storage_for_type<T, size_t count = 1>
and
storage_for_size<size_t>
where storage_for_size determines the minimum necessary alignment based on
the size, as discussed.
-Howard
Tony
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net