Boost logo

Boost :

Subject: Re: [boost] ASIO into the standard
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2014-07-11 20:49:45


On 11 Jul 2014 at 21:06, Daniel James wrote:
> >
> > My understanding is that the allocators have to be used for all
> > dynamic allocation. If this is not explicitly worded in the standard,
> > then it should be. Otherwise allocators simply are not as useful with
> > any other interpretation.

I assume by allocators you mean specifically STL allocators?

> I looked this up earlier, as I thought the same. 23.2.1.7 says:
>
> "Unless otherwise specified, all containers defined in this clause
> obtain memory using an allocator (see 17.6.3.5)."
>
> Which suggests to me that all allocation is done using the allocator.
> I suppose debug info could be considered something that isn't obtained
> by the container, as it can be external, but I wouldn't have thought
> that for things like buckets.

The standard definitely means an STL allocator, not simply "an
allocator"?

It's not just debug info though. I can think of a number of STL
containers which could use non-STL allocation for internal stuff -
for example, if you create a threadsafe STL container you could
allocate an internal mutex, and it would seem excessive to require
using an externally supplied allocator for that too. Furthermore, a
std::mutex under the hood will almost certainly do some more
allocation.

You might argue this isn't really allocation of memory. So to
counterexample, what about a STL container of shared memory regions?
Or a STL container of memory mapped files? You'd want the allocator -
given it has 4Kb granularity - to only be used for value types only.
I suppose you could specialise the rebind to avoid this happening,
but we're beginning to chase our tail now.

> 23.2.1.3 says:
>
> "For the components affected by this subclause that declare an
> allocator_type, objects stored in these
> components shall be constructed using the
> allocator_traits<allocator_type>::construct function and
> destroyed using the allocator_traits<allocator_type>::destroy function
> (20.7.8.2). These functions
> are called only for the container´s element type, not for internal
> types used by the container."
>
> But that's specifying construction, not allocation (btw. I get this
> wrong in unordered, I'll fix it soon).

I have been lazy as it's test code, and implemented a move assignment
like this for an internal item_type due to value_type.first being
const:

    struct item_type
    {
      value_type p;
      size_t hash;
      item_type() : hash(0) { }
      item_type(value_type &&_p, size_t _hash) BOOST_NOEXCEPT :
p(std::move(_p)), hash(_hash) { }
      item_type(item_type &&o) BOOST_NOEXCEPT : p(std::move(o.p)),
hash(o.hash) { }
      item_type &operator=(item_type &&o) BOOST_NOEXCEPT
      {
        this->~item_type();
        new (this) item_type(std::move(o));
        return *this;
      }

Which would normally be unsafe, except everything is noexcept, so I
actually think this is okay except for the fact that the allocator's
construct and destroy aren't being invoked.

> Did I miss anything? I don't claim any expertise here.

Me neither. When do C++ programmers normally implement STL containers
as part of their normal day job? Probably only Stephan. Anyway,
they're a bitch to do correctly and keep performance reasonable.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ 
http://ie.linkedin.com/in/nialldouglas/



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk