原子compare_exchange,但是基于标志被设置,而不是相等吗?

时间:2019-01-28 17:16:28

标签: c++ multithreading concurrency atomic

std :: atomic提供compare_exchange_strong(a,b)测试基础值当前是否为“ a”,如果是,则以原子/线程安全的方式将其替换为“ b”。

是否有任何无锁的原子方式来执行类似的操作,但是它不会将“ b”视为标志,而是将其替换为“ b”,如果基础值具有该标志,则执行替换设置吗?

所以原则上类似

bool compare_exchange_flags(std::atomic<int>& underlying, int& flag, int replacement)
{
  auto tmp = underlying.load();

  if((tmp & flag) == flag) // only perform replacement if flag is set
  {
    flag = tmp; // emulate compare_exchange_strong, where expected value is replaced with actual value
    underlying = replacement;
    return true;
  } else {
    flag = underlying.load();
    return false;
  }
}

仅在可以正常工作的版本中才可以;)(以上操作当然不是原子的)

谢谢!


对于上下文:这用于消息总线。该总线具有与某些状态(如READABLE,WRITEABLE)关联的内存区域。

每个状态都需要使用一些标志来增强-例如,一个状态可以只是“可写”,这意味着写入器可以将数据自由地写入片段(读取器当前正在旋转/繁忙的轮询)。 或者它可能是“ WRITEABLE | SIGNALED”,这意味着写程序可以获取该内存以进行写操作,但是一旦写入数据以通知读者,就需要触发一个事件。

所以(从概念上来说,这不是实际的代码-只是粗略地演示)类似

void send(...)
{
  auto expected = WRITEABLE;
  if(compare_exchange_flags(status, expected, WRITE_RESERVED))
  {
    // ... write data ...

    status = WRITTEN;

    if((expected & SIGNALED) = SIGNALED)
      wakeUpReaders();
  } else {
    tryAnotherRegion();
  }
}

1 个答案:

答案 0 :(得分:2)

没有这样的指示。但是,这类操作通常是通过循环执行的,该循环尝试在值具有标志的情况下交换值:

bool replace_if_flag(std::atomic<int>& underlying, int flag, int replacement){

  auto tmp = underlying.load();

  if(!(tmp & flag)) return false;

  while (!underlying.compare_exchange_weak(tmp,replacement)){
    if(!(tmp & flag)) return false;
    }

  return true;
  }