Объем барьера памяти - PullRequest
       10

Объем барьера памяти

0 голосов
/ 13 сентября 2018

Я не уверен, каковы границы барьеров памяти std::memory_order_release или std::memory_order_acquire.Ниже приведен пример из cppreference .Я подправил код, чтобы сделать мою точку зрения:

#include <atomic>
#include <cassert>
#include <string>
#include <thread>
#include <iostream>

std::atomic<std::string*> ptr;

void producer()
{
  std::string* p  = new std::string("Hello");

  ptr.store(p, std::memory_order_release);
}

bool acquire(std::string* p2)
{
  while (!(p2 = ptr.load(std::memory_order_acquire)));

  return p2 != nullptr;
}

void consumer()
{
  std::string* p2 {nullptr};

  // while (!(p2 = ptr.load(std::memory_order_acquire))); // prints "makes sense"
  assert(acquire(p2)); // prints "what's going on?"

  if (p2 == nullptr)
  {
    std::cout << "what's going on?" << std::endl;
  }
  else
  { 
    std::cout << "makes sense" << std::endl;
  }
}

int main()
{
  std::thread t1(producer);
  std::thread t2(consumer);
  t1.join(); t2.join();
}

Вывод приведенного выше кода what's going on?

Я знаком (не эксперт) с барьерами памяти.Из приведенного выше теста у меня есть следующие вопросы:

  1. std::memory_order_acquire, используемый в функции acquire(), используется только для области действия acquire(), основываясь на результатах программыпоскольку uncommenting while(...) печатает ожидаемый вывод, "имеет смысл".Имеет ли это смысл?я что-то упускаю?

  2. Как можно напечатать "что происходит?", assert(acquire(p2)) дает понять, что p2 не nullptr, но каким-то образом читает *Значение 1025 * в условном выражении if.Я не эксперт по правилам исполнения ордеров, но я ожидаю, что p2 = nullptr будет признано, прежде чем вызывать acquire(), since acquire() зависит от этого.

1 Ответ

0 голосов
/ 13 сентября 2018
  1. std::memory_order_acquire, используемая в функции acquire(), используется только для области действия acqu ()

Нет. Он применяется к потоку и не связан функцией.

  1. Как можно напечатать "что происходит?"

Поскольку вы изменяете копию указателя. Изменения:

bool acquire(std::string* p2)

до:

bool acquire(std::string*& p2)

чтобы сделать функцию ссылкой на тот же указатель, который был передан ей.

...