代码之家  ›  专栏  ›  技术社区  ›  Bogey

原子比较交换,但基于设置的标志,而不是相等?

  •  3
  • Bogey  · 技术社区  · 6 年前

    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;
      }
    }
    

    谢谢


    对于上下文:这是针对消息总线的。此总线具有与某些状态(如可读、可写)关联的内存区域。

    或者它可以是“可写的|有信号的”,这意味着写入程序可以获取该内存进行写入,但需要在写入数据后触发事件以通知读卡器。

    所以(从概念上讲,这不是实际的代码——只是粗略地演示一下)类似于

    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 回复  |  直到 6 年前
        1
  •  2
  •   Oliv    6 年前

    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;
      }