如何在shared_ptr <t>和shared_ptr <const t =“”>中使用boost :: atomic_store?

时间:2017-09-11 11:57:13

标签: c++ boost shared-ptr atomic

在我的情况下Tpcl::PointCloud<pcl::PointXYZ>>,但问题应该代表任何类型T。以下示例产生错误:

using pc = pcl::PointCloud<pcl::PointXYZ> >;
boost::shared_ptr<pc> p(new pc);
boost::shared_ptr<const pc> const_p(new pc);

// This is legal
const_p = p;

// The atomic equivalent is not
boost::atomic_store(&const_p, p);

问题在于boost::atomic_store期望两个参数都是T*T,但这些参数被认为是不同的类型,尽管它分配{非常安全{1}}到p。以下内容也不起作用。

const_p

尽管上面基本上将boost::atomic_store(&const_p, const_cast<boost::shared_ptr<const pc> > (p)); 转换为pc*这是非常安全的,但它会产生关于const pc*无法转换为其他类型的错误。我理解,因为const_cast是一个模板参数,它被认为是pc类型的一部分,而不是cv资格。以下工作

shared_ptr

但是,它会产生额外的不必要boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p)); 。我理解boost::shared_ptr也是如此。如果不再需要boost::const_pointer_cast<const pc>(p),可以避免这种情况。

p

这仍然会创建一个额外的对象,但它不重要,因为引用计数没有被修改,这是因为原子性而复制boost::atomic_store(&const_p, boost::shared_ptr<const pc>(std::move(p)); 的昂贵部分。

恰好这种情况发生在我的代码的非关键部分,所以我对上述情况很好,但我想知道以后参考:如果shared_ptr不是一个选项如何在没有创建不必要的临时指针的情况下,以原子方式将std::move存储到boost::shared_ptr<T>?这应该是可能的,因为通过boost::shared_ptr<const T>查看T是安全的,但我无法找到方法。

1 个答案:

答案 0 :(得分:2)

  

我理解因为pc是模板参数,所以它被认为是shared_ptr类型的一部分,而不是cv资格。

是的,这被称为“不可推翻的背景”。

  

以下工作

boost::atomic_store(&const_p, boost::shared_ptr<const pc>(p));
     

但是,它会产生额外的不必要boost::shared_ptr。这是我的   理解同样如此   boost::const_pointer_cast<const pc>(p)如果p为no,则可以避免这种情况   需要更长时间。

嗯,出乎意料的是,你总是得到副本:

template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
    boost::detail::spinlock_pool<2>::scoped_lock lock( p );
    p->swap( r );
}

注意第二个参数是按值。这一点,解决了这个谜团:

<强> Live On Coliru

#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 
#include <boost/atomic.hpp>

namespace pcl {
    struct PointXYZ {};
    template <typename P> struct PointCloud {
    };
}

int main() {
    using pc = pcl::PointCloud<pcl::PointXYZ>;
    boost::shared_ptr<pc> p             = boost::make_shared<pc>();
    boost::shared_ptr<const pc> const_p = boost::make_shared<pc>();

    // This is legal
    const_p = p;

    // The atomic equivalent is too
    boost::atomic_store<pc const>(&const_p, p);
}
  

如果std :: move不是一个选项,那么如何以原子方式存储a   boost :: shared_ptr到boost :: shared_ptr没有   创建一个不必要的临时指针的开销?

你做不到。以这种方式看待它:加载/存储意味着适用于原子无锁实现的微不足道的操作。他们做了一件事,他们做得很好¹。

进行隐式转换不是该函数的责任。

我建议使用包装器函数,甚至使用ADL从你自己的命名空间中解决你自己的重载。