如何将boost::atomic_store与shared_ptr和shared_ptr一起使用?

2023-12-23

就我而言T is pcl::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* and T,但尽管事实上分配是完全安全的,但它们被认为是不同的类型p to const_p。下面的也不起作用。

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

尽管上面基本上铸造了pc* to const pc*这是完全安全的,它会产生一个关于const_cast无法转换为不同类型。我明白是因为pc是一个模板参数,它被认为是类型的一部分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> to a boost::shared_ptr<const T>没有创建不必要的临时指针的开销?应该是可以的,因为查看是安全的T通过一个const T*,但我想不出办法。


据我所知,因为 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 不存在,则可以避免这种情况 更需要。

好吧,令人惊讶的是,你总是会得到副本:

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 http://coliru.stacked-crooked.com/a/5013fb09649d54d6

#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 不是一种选择,那么如何原子地存储一个 boost::shared_ptr 到 boost::shared_ptr 没有 创建不必要的临时指针的开销?

你不能。这样看:加载/存储意味着是适合原子无锁实现的琐碎操作。他们只做一件事,而且做得很好。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将boost::atomic_store与shared_ptr和shared_ptr一起使用? 的相关文章

随机推荐