Commit 78d7cd51 authored by Mark Williams's avatar Mark Williams Committed by Facebook Github Bot

Move shared_ptr_internals methods out of the class

Summary:
When they come before the explicit instantiations of Rob, icc fails to
compile certain combintions of calls.

Reviewed By: alexeyt

Differential Revision: D10144943

fbshipit-source-id: ce63a4d289f64d1d644b116ab99b45b9da013162
parent 3cc2f315
...@@ -40,82 +40,25 @@ class shared_ptr_internals { ...@@ -40,82 +40,25 @@ class shared_ptr_internals {
typedef std::_Sp_counted_base<std::_S_atomic> counted_base; typedef std::_Sp_counted_base<std::_S_atomic> counted_base;
template <typename T> template <typename T>
using CountedPtr = std::shared_ptr<T>; using CountedPtr = std::shared_ptr<T>;
template <typename T> template <typename T>
static counted_base* get_counted_base(const std::shared_ptr<T>& bar) { static counted_base* get_counted_base(const std::shared_ptr<T>& bar);
// reinterpret_pointer_cast<const void>
// Not quite C++ legal, but explicit template instantiation access to
// private members requires full type name (i.e. shared_ptr<const void>, not
// shared_ptr<T>)
const std::shared_ptr<const void>& ptr(
reinterpret_cast<const std::shared_ptr<const void>&>(bar));
return (ptr.*fieldPtr(access_shared_ptr{})).*fieldPtr(access_base{});
}
static void inc_shared_count(counted_base* base, long count) { static void inc_shared_count(counted_base* base, long count);
// Check that we don't exceed the maximum number of atomic_shared_ptrs.
// Consider setting EXTERNAL_COUNT lower if this CHECK is hit.
FOLLY_SAFE_CHECK(
base->_M_get_use_count() + count < INT_MAX,
"atomic_shared_ptr overflow");
__gnu_cxx::__atomic_add_dispatch(
&(base->*fieldPtr(access_use_count{})), count);
}
template <typename T> template <typename T>
static void release_shared(counted_base* base, long count) { static void release_shared(counted_base* base, long count);
// If count == 1, this is equivalent to base->_M_release()
if (__gnu_cxx::__exchange_and_add_dispatch(
&(base->*fieldPtr(access_use_count{})), -count) == count) {
base->_M_dispose();
if (__gnu_cxx::__exchange_and_add_dispatch(
&(base->*fieldPtr(access_weak_count{})), -1) == 1) {
base->_M_destroy();
}
}
}
template <typename T> template <typename T>
static T* get_shared_ptr(counted_base* base) { static T* get_shared_ptr(counted_base* base);
// See if this was a make_shared allocation
auto inplace = base->_M_get_deleter(typeid(std::_Sp_make_shared_tag));
if (inplace) {
return (T*)inplace;
}
// Could also be a _Sp_counted_deleter, but the layout is the same
using derived_type = std::_Sp_counted_ptr<const void*, std::_S_atomic>;
auto ptr = reinterpret_cast<derived_type*>(base);
return (T*)(ptr->*fieldPtr(access_counted_ptr_ptr{}));
}
template <typename T> template <typename T>
static T* release_ptr(std::shared_ptr<T>& p) { static T* release_ptr(std::shared_ptr<T>& p);
auto res = p.get();
std::shared_ptr<const void>& ptr(
reinterpret_cast<std::shared_ptr<const void>&>(p));
ptr.*fieldPtr(access_shared_ptr_ptr{}) = nullptr;
(ptr.*fieldPtr(access_refcount{})).*fieldPtr(access_base{}) = nullptr;
return res;
}
template <typename T> template <typename T>
static std::shared_ptr<T> get_shared_ptr_from_counted_base( static std::shared_ptr<T> get_shared_ptr_from_counted_base(
counted_base* base, counted_base* base,
bool inc = true) { bool inc = true);
if (!base) {
return nullptr;
}
std::shared_ptr<const void> newp;
if (inc) {
inc_shared_count(base, 1);
}
newp.*fieldPtr(access_shared_ptr_ptr{}) =
get_shared_ptr<const void>(base); // _M_ptr
(newp.*fieldPtr(access_refcount{})).*fieldPtr(access_base{}) = base;
// reinterpret_pointer_cast<T>
auto res = reinterpret_cast<std::shared_ptr<T>*>(&newp);
return std::move(*res);
}
private: private:
/* Accessors for private members using explicit template instantiation */ /* Accessors for private members using explicit template instantiation */
...@@ -185,5 +128,87 @@ template struct shared_ptr_internals::Rob< ...@@ -185,5 +128,87 @@ template struct shared_ptr_internals::Rob<
shared_ptr_internals::access_refcount, shared_ptr_internals::access_refcount,
&std::__shared_ptr<const void, std::_S_atomic>::_M_refcount>; &std::__shared_ptr<const void, std::_S_atomic>::_M_refcount>;
template <typename T>
inline shared_ptr_internals::counted_base*
shared_ptr_internals::get_counted_base(const std::shared_ptr<T>& bar) {
// reinterpret_pointer_cast<const void>
// Not quite C++ legal, but explicit template instantiation access to
// private members requires full type name (i.e. shared_ptr<const void>, not
// shared_ptr<T>)
const std::shared_ptr<const void>& ptr(
reinterpret_cast<const std::shared_ptr<const void>&>(bar));
return (ptr.*fieldPtr(access_shared_ptr{})).*fieldPtr(access_base{});
}
inline void shared_ptr_internals::inc_shared_count(
counted_base* base,
long count) {
// Check that we don't exceed the maximum number of atomic_shared_ptrs.
// Consider setting EXTERNAL_COUNT lower if this CHECK is hit.
FOLLY_SAFE_CHECK(
base->_M_get_use_count() + count < INT_MAX, "atomic_shared_ptr overflow");
__gnu_cxx::__atomic_add_dispatch(
&(base->*fieldPtr(access_use_count{})), count);
}
template <typename T>
inline void shared_ptr_internals::release_shared(
counted_base* base,
long count) {
// If count == 1, this is equivalent to base->_M_release()
if (__gnu_cxx::__exchange_and_add_dispatch(
&(base->*fieldPtr(access_use_count{})), -count) == count) {
base->_M_dispose();
if (__gnu_cxx::__exchange_and_add_dispatch(
&(base->*fieldPtr(access_weak_count{})), -1) == 1) {
base->_M_destroy();
}
}
}
template <typename T>
inline T* shared_ptr_internals::get_shared_ptr(counted_base* base) {
// See if this was a make_shared allocation
auto inplace = base->_M_get_deleter(typeid(std::_Sp_make_shared_tag));
if (inplace) {
return (T*)inplace;
}
// Could also be a _Sp_counted_deleter, but the layout is the same
using derived_type = std::_Sp_counted_ptr<const void*, std::_S_atomic>;
auto ptr = reinterpret_cast<derived_type*>(base);
return (T*)(ptr->*fieldPtr(access_counted_ptr_ptr{}));
}
template <typename T>
inline T* shared_ptr_internals::release_ptr(std::shared_ptr<T>& p) {
auto res = p.get();
std::shared_ptr<const void>& ptr(
reinterpret_cast<std::shared_ptr<const void>&>(p));
ptr.*fieldPtr(access_shared_ptr_ptr{}) = nullptr;
(ptr.*fieldPtr(access_refcount{})).*fieldPtr(access_base{}) = nullptr;
return res;
}
template <typename T>
inline std::shared_ptr<T>
shared_ptr_internals::get_shared_ptr_from_counted_base(
counted_base* base,
bool inc) {
if (!base) {
return nullptr;
}
std::shared_ptr<const void> newp;
if (inc) {
inc_shared_count(base, 1);
}
newp.*fieldPtr(access_shared_ptr_ptr{}) =
get_shared_ptr<const void>(base); // _M_ptr
(newp.*fieldPtr(access_refcount{})).*fieldPtr(access_base{}) = base;
// reinterpret_pointer_cast<T>
auto res = reinterpret_cast<std::shared_ptr<T>*>(&newp);
return std::move(*res);
}
} // namespace detail } // namespace detail
} // namespace folly } // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment