两个unique_ptr< T>的无锁交换。 [英] Lock-free swap of two unique_ptr<T>

查看:99
本文介绍了两个unique_ptr< T>的无锁交换。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不保证交换两个 unique_ptr 是线程安全的。

Swapping two unique_ptrs is not guaranteed to be threadsafe.

std::unique_ptr<T> a, b;
std::swap(a, b); // not threadsafe

因为我需要原子指针交换,而且因为我喜欢<$ c的所有权处理$ c> unique_ptr ,有没有一种简单的方法将两者组合?

Since I need atomic pointer swaps and since I like the ownership handling of unique_ptr, is there a simple way to combine them both?

编辑:如果无法做到这一点,我欢迎其他选择。我至少想做这样的事情:

If this is not possible, I am open for alternatives. I at least want to do something like this:

threadshared_unique_ptr<T> global;

void f() {
   threadlocal_unique_ptr<T> local(new T(...));
   local.swap_content(global); // atomically for global
}

在C +中,这种做法的惯用方式是什么+11?

What is the idiomatic way of doing this in C++11?

推荐答案

两个指针的无锁交换



似乎没有通用的无锁解决方案可以解决此问题。为此,您可能需要以原子方式将新值写入两个不连续的内存位置。这称为 DCAS ,但在Intel处理器中不可用。

Lock-free swapping of two pointers

It seems there is no general lock-free solution for this problem. To do this, you need a possibility to atomically write new values into two non-continous memory locations. This is called DCAS, but it is not available in Intel processors.

这是可能的,因为只需要将新值自动保存到 global 并接收其旧值即可。我的第一个想法是使用 CAS 操作。看看下面的代码来了解一下:

This one is possible, as it is only needed to atomically save new value into global and receive its old value. My first idea was to use CAS operation. Take a look at the following code to get an idea:

std::atomic<T*> global;

void f() {
   T* local = new T;
   T* temp = nullptr;
   do {
       temp = global;                                                   // 1
   } while(!std::atomic_compare_exchange_weak(&global, &temp, local));  // 2

   delete temp;
}

步骤


  1. temp
  2. 中记住当前的 global 指针
  3. 如果全局仍等于<,则将本地保存到全局 code> temp (其他线程未更改)。如果不是这样,请再试一次。

  1. Remember current global pointer in temp
  2. Save local to global if global is still equal to temp (it wasn't changed by other thread). Try again if this is not true.

实际上, CAS 在那里过大,因为在更改之前,我们不会对旧的 global 值进行任何特殊处理。因此,我们只可以使用原子交换操作:

Actually, CAS is overkill there, as we do not do anything special with old global value before it is changed. So, we just can use atomic exchange operation:

std::atomic<T*> global;

void f() {
   T* local = new T;
   T* temp = std::atomic_exchange(&global, local);
   delete temp;
}

请参见乔纳森(Jonathan)的答案,以获得更简短,更优雅的解决方案。

See Jonathan's answer for even more short and elegant solution.

无论如何,您都必须编写自己的智能指针。您不能在标准 unique_ptr 中使用此技巧。

Anyway, you will have to write your own smart pointer. You can't use this trick with standard unique_ptr.

这篇关于两个unique_ptr&lt; T&gt;的无锁交换。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆