为什么std :: atomic :: compare_exchange_xxx()的预期参数不是const&?

时间:2018-10-14 09:07:08

标签: c++ c++11 std atomic

我确定我将要面对一刹那的时刻,但这是这样的:

std::atomic::compare_expected_*的原型是

bool compare_exchange_strong (T& expected, T val,
       memory_order sync = memory_order_seq_cst) volatile noexcept;

为什么expected不是const T &

static const handle_t INVALID_HANDLE = 0;
...
std::atomic<handle_t> handle(INVALID_HANDLE);
...
handle.compare_exchange_strong(INVALID_HANDLE, newValue);

交换方法肯定不需要修改期望值吗?

3 个答案:

答案 0 :(得分:6)

TL; DR:因为如果期望的参数是const引用,那么在交换失败时compare_exchange将无法对其进行修改。


您将期望期望值都提供给compare_exchange。 如果发现与您提供的值不同的值,它将修改您的期望值。在这种情况下,期望值不会被您提供的期望值代替(即,它无法交换,因此您可能要尝试再次交换该值)。

通常,您希望循环使用这些功能,因此修改提供的期望值很有意义,因为它为您提供了期望值的更新版本。

考虑以下原子:

std::atomic<int> a = 7;

,您想将a的值加倍:

int expected = a.load(), desired;
do {
  desired = 2 * expected;
} while (!a.compare_exchange_weak(expected, desired));

在上面的代码中,如果a在交换发生之前被另一个线程更改,则expectedcompare_exchange更新为当前值a尝试进行交换(即失败时)的信息。

否则,如果在失败的情况下expected未被compare_exchange修改,则必须在循环的每次迭代中加载a的值以更新{{1} }:

expected

答案 1 :(得分:2)

它会在失败时修改expected

答案 2 :(得分:1)

cppreference.com

  

以原子方式比较.belowContent.outerZeroSize的对象表示,如果它们按位相等,则用所需的对象表示替换(执行读-修改-写操作)。否则,将存储在class Building(models.Model): bid = models.CharField(max_length=10, primary_key=True) name = models.CharField(max_length=255, unique=True) class Meta: ordering = ['bid'] def __str__(self): return f'{self.bid}' class Room(models.Model): building = models.ForeignKey(Building, on_delete=models.CASCADE, related_name='rooms') number = models.PositiveIntegerField() availability = models.BooleanField(default=False) power = models.BooleanField(default=False) class Meta: ordering = ['building', 'number'] unique_together = ['building', 'number'] def __str__(self): return f'{self.building.bid}/{self.number}' class Occurrence(models.Model): date = models.DateField('Date') start_period = models.ForeignKey(Period, on_delete=models.CASCADE, related_name='start_at') end_period = models.ForeignKey(Period, on_delete=models.CASCADE, related_name='end_at') class Meta: abstract = True class Period(models.Model): start = models.TimeField() end = models.TimeField() objects = PeriodManager() class Meta: ordering = ['start'] def __str__(self): return f'{self.start}-{self.end}' def check_time(self): return True if self.start < self.end else False def check_overlap(self): pass class TimetableModel(models.Model): class Meta: abstract =True 中的实际值加载到*this 中(执行加载操作)。