On 11/06/15 23:32 +0800, Fan You wrote:
Hi,
This is my first patch for GSoC project: extend shared_ptr to support
arrays.
Changes are made in these files:
* libstdc++-v3/include/bits/shared_ptr_base.h : Renamed _Sp_counted_deleter
to _Sp_counted_array, changed _shared_count construct from _Sp_counted_ptr
to _Sp_counted_array.
Why?
As far as I can see it has nothing to do with arrays.
* libstdc++-v3/include/experimental/memory : add shared_ptr into
fundamentals_v1
Is it too long for reviewing? Should I detach them into different patches?
Any comments?
General comments:
Please fix the lines that consist of nothing but whitespace, they
should just be empty lines.
You're going to need tests!
Comments on changes to include/bits/shared_ptr_base.h:
This type should not be declared when including <memory>:
+ namespace experimental{
+ inline namespace fundamentals_v1 {
+ template<typename _Tp>
+ class enable_shared_from_this;
+ }
+ }
+
You will need to find another way to make
experimental::enable_shared_from_this work, without declaring it in
<bits/shared_ptr.h> (e.g. add a new type with a reserved name and make
experimental::enable_shared_from_this use that, and only declare
experimental::enable_shared_from_this in <experimental/memory>).
Please review the patch to ensure you are not reverting my recent
changes on trunk e.g.
-#if __cpp_rtti
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2400. shared_ptr's get_deleter() should use addressof()
- return __ti == typeid(_Deleter)
- ? std::__addressof(_M_impl._M_del())
- : nullptr;
+#ifdef __GXX_RTTI
+ return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr;
#else
return nullptr;
#endif
This should definitely not be in the patch, it's a regression.
You've also reverted changes to _Sp_counted_deleter::_M_destroy().
Maybe I'm wrong, but I don't tink it's necessary to provide three
partial specializations:
+ // alias for original __shared_ptr
+ template <typename _Tp, _Lock_policy _Lp>
+ class __shared_ptr<__libfund_v1<_Tp>, _Lp> : public __shared_ptr<_Tp, _Lp>
+ {
...
+ // array support
+ template<typename _Tp, _Lock_policy _Lp, unsigned N>
+ class __shared_ptr<__libfund_v1<_Tp[N]>, _Lp>
+ {
...
+ template<typename _Tp, _Lock_policy _Lp>
+ class __shared_ptr<__libfund_v1<_Tp[]>, _Lp>
Isn't it possible to provide just one, which handles all three cases?
// Implementation of std::experimental::shared_ptr
template <typename _Tp, _Lock_policy _Lp>
class __shared_ptr<__libfund_v1<_Tp>, _Lp>
{
using _Deleter_type = typename conditional<is_array<_Tp>::value,
_Normal_deleter, _Array_deleter>::type;
public:
using element_type = typename remove_extent<_Tp>::type;
template<typename _Tp1>
__shared_ptr(_Tp1* __p)
: _M_ptr(__p), _M_refcount(__p, Deleter_type{})
Alternatively, have one partial specialization for non-arrays (which
derives from __shared_ptr<_Tp>, as you have now) and another for
arrays. That could be done like so:
template<typename _Tp, bool = is_array<_Tp>::value>
struct __libfund_v1 { };
// Implementation of std::experimental::shared_ptr for non-arrays
template <typename _Tp, _Lock_policy _Lp>
class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
: public __shared_ptr<_Tp>
{
// ...
}
// Implementation of std::experimental::shared_ptr for arrays
template <typename _Tp, _Lock_policy _Lp>
class __shared_ptr<__libfund_v1<_Tp, true>, _Lp>
: public __shared_ptr<_Tp>
{
// ...
}
It should be possible for the same partial specialization to work for
shared_ptr<T[]> and shared_ptr<T[N]>.
Even if that isn't possible, this is wrong:
+ using element_type = _Tp[N];
And in your new _weak_ptr<__libfund_v1<_Tp>, _Lp> specialization this
is wrong:
+ using element_type = _Tp;
It looks to me as though calling experimental::__weak_ptr<T>::lock()
will return the wrong type of __shared_ptr. That might not be
important.
Comments on changes to include/experimental/memory:
I don't see a definition of experimental::weak_ptr.
The way you've defined experimental::__shared_ptr means it doesn't
support arrays (apologies if you've done what I suggested ... it
obviously wasn't right).
I think it should be something like this:
+ //for non default lock policy
+ template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
+ using __shared_ptr = std::__shared_ptr<__libfund_v1<_Tp>, _Lp>;
i.e. experimental::__shared_ptr<T[]> should use the partial
specialization for arrays.
Then experimental::shared_ptr can just use that:
+ template<typename _Tp>
+ class shared_ptr : public __shared_ptr<_Tp>
+ {