This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [GSoC] __enable_shared_from_this_helper


Just for background, maybe Jon's stackoverflow answer helps:
<http://stackoverflow.com/questions/13912286/intrusive-ptr-in-c11>

On Tue, Apr 28, 2015 at 7:21 PM, Fan You <youfan.noey@gmail.com> wrote:
> To make sure I understand the question.
>
> Shared_count actually allocate the memory which is exact the same size
> as single _Sp_cp_type object by doing this:
>
>> _Sp_cp_type* __mem = _Alloc_traits::allocate(__a2, 1);

This is correct.

> However, assume we have some usage like this:
>>
>> auto sp1 = std::experimental::make_shared<int>(5);
>>
>> auto sp2 = std::experimental::make_shared<int[5]>(5);
>
>
> Both of them use std::allocator<int> as an allocator. They will have

That's what you need to fix :).

> same behavior when allocate memory (which only allocate single
> _Sp_cp_type object.) And it's clearly not right to do something like:
>
>> _Sp_cp_type* __mem = _Alloc_traits::allocate(__a2, size);
>
>
> So, what's the best method to allocate the right size for array type?

Looking at three derived classes of _Sp_counted_base:
1) _Sp_counted_ptr, a simple _M_ptr with ownership and default deleter
("delete _M_ptr").

2) _Sp_counted_deleter, a _M_ptr with user customized alloc and deleter.

3) _Sp_counted_ptr_inplace, a piece of *data* instead of a pointer,
who doesn't need to be deallocated separately.

The reason for 1) is less overhead; for 2) is user needs; for 3), is
less times of allocation.

Interestingly, I think _Sp_counted_ptr can be implemented in terms of
_Sp_counted_deleter, with default allocator and deleter, both of which
cost 0 bytes for storage, after ebo. Maybe it's just for readability?

The question worth to ask is: are these strategies can be used in
shared_ptr for array? For each of them, if so, how?
For 1), Use delete[].

For 2), User will offer allocator and deleter, but we still need to
maintain the length.

For 3), User will offer allocator, we maintain the length, let's say
n, and include n objects *all adjacent with other types of data*, like
two counters in _Sp_counted_base and the length. This is possible in C
using malloc and flexible member array, but as of my knowledge, it's
hard/impossible to implement this using C++ allocator? It maybe
possible for a small sized _Tp, so we just allocate a few more slots
for our extra data (and also we need to handle alignment well); but if
_Tp is large, then there's no way to do this?

The conclusion is, adopt 1) for potential less overhead; adopt 2) for
user needs; drop 3) at least for now, since it's hard to implement.


Coming back to your question, I don't think you need to care about
make_shared optimization :)

But yeah, for implementing 2) you still need to propagate the length.
This depends on how you implement your shared_ptr array, but I'm not
sure how you do this currently:

1) If you implement shared_ptr<int[]> in terms of shared_ptr<int> with
a special allocator, then this allocator needs to carry the length and
be able to wrap an user-specified allocator:
    template<typename _Alloc>
    class __allocator_array_wrapper
    {
    public:
      /* typedefs */
    public:
      /* ... */
      pointer allocate(size_type __n, /*...*/)
      {
        _GLIBCXX_DEBUG_ASSERT(__n == 1);
        return _M_alloc.allocate(_M_length, /*...*/);
      }

      void deallocate(pointer __p, size_type __n)
      {
        _GLIBCXX_DEBUG_ASSERT(__n == 1);
        _M_alloc.deallocate(__p, _M_length);
      }
      /* ... */
    private:
      size_t _M_length;
      _Alloc _M_alloc; // just for illustration here; may need ebo.
    };

2) If you started from scratch, just create a new __shared_count ctor
overloading (with a new tag if it's necessary), which takes the
length.

I don't know every details about allocators or even shared_ptr, so
please point out the mistakes :).

Thanks!


-- 
Regards,
Tim Shen


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]