Косвенный атоми c своп для структуры с указателем - PullRequest
0 голосов
/ 25 февраля 2020

Я хочу атомарно поменять две большие области памяти, определенные как структура VValue. Поскольку размер структуры больше, чем long, отсутствует архитектурная поддержка для прямого сравнения и обмена двух структур. Однако один из способов - поменять местами указатели двух структур и косвенно поменять местами памяти.

Ниже мой код, который должен поменять местами oldValue с b. Встроенная функция сравнения и обмена используется внутри do-while l oop, чтобы убедиться, что значение oldValue не изменилось, возможно, другими потоками во время обмена (этот фрагмент кода является упрощенной версией более сложный своп с другими условиями. Условия для краткости удалены.


  template<typename A, typename B, typename C, typename D>
  struct VStructType{
    A a;
    B b;
    C c;
    D d;

    VStructType () {
      ;

    }

    VStructType (A a, B b, C c, D d) {
      this->a = a;
      this->b = b;
      this->c = c;
      this->d = d;

    }

  };

  typedef VStructType<uint32_t,uint32_t,uint32_t,uint32_t> VValue;

  bool swap(VValue* oldValue, VValue b)
  {
    bool r = 0;
    VValue* c;
    VValue *w = new VValue();

    do{
      c = oldValue;
      w->a = b.a;
      w->b = b.b;
      w->c = b.c;
      w->d = b.d;
    } while (!(r = __sync_bool_compare_and_swap(&oldValue, c, w)));
    return r;
  }

  int main()
  {
    VValue oldValue = VValue(1,2,3,4);
    VValue b = VValue(10,12,2,8);
    swap(&oldValue, b);
  }

Проблема в том, что после свопинга внутри функции свопинга значение oldValue изменяется на новое, но после При возврате из функции подкачки oldValue не изменяется. Похоже, что ссылка на oldValue является временной ссылкой, и когда происходит свопинг, она меняет только новую ссылку, а не фактический указатель на oldValue. Причина, по которой ссылка передается функции __sync_bool_compare_and_swap, заключается в том, что первый аргумент является указателем на переменную, значение которой нужно сравнить с .

Мои вопросы:

1) Есть ли способ передать указатель указателя oldValue непосредственно в функцию __sync_bool_compare_and_swap?

2) Это Подход возможен, когда oldValue является элементом в массиве?

Примечание: используйте g++ -latomic -std=gnu++11 для компиляции.

1 Ответ

0 голосов
/ 26 февраля 2020

Хитрость заключается в том, чтобы передать ссылку указателя на oldValue в функцию свопинга и изменить своп следующим образом:

bool swap(VValue** oldValue, VValue b)
  {
    bool r = 0;
    VValue* c;
    VValue *w = new VValue();

    do{
      c = *oldValue;
      w->a = b.a;
      w->b = b.b;
      w->c = b.c;
      w->d = b.d;
    } while (!(r = __sync_bool_compare_and_swap(oldValue, c, w)));
    if(!r)
      delete w;
    return r;
  }

int main()
  {
    VValue* oldValue = new VValue(1,2,3,4);
    VValue b = VValue(10,12,2,8);
    swap(&oldValue, b);
  }
...