Безопасен ли порядок операций? - PullRequest
3 голосов
/ 14 июля 2020

У меня есть std::vector, который используется для передачи сообщения в поток. Вектор защищен мьютексом:

vector<int> messages;
std::mutex m;

void postmessage (int msg) {
  {
    std::unique_lock Lock (m);
    messages.push_back (msg);
  }
}

Когда поток просыпается, он захватывает всю очередь сообщений следующим образом:

  const auto my_messages = [this] {
    std::unique_lock Lock (m);
    return move (messages);     
  } ();

Затем он обрабатывает my_messages. Вопросы:

  1. Гарантированно ли это оставит вектор в пустом состоянии? Другими словами, это приложение конструктора (7) на cppreference , которое гарантирует, что вектор останется пустым?

  2. Гарантированы ли операции над messages завершить до разблокировки мьютекса? Другими словами, является ли это потокобезопасным?

1 Ответ

3 голосов
/ 14 июля 2020
  1. Гарантированно ли это оставит вектор в пустом состоянии?

Да, возвращаемое значение построено на основе перемещения из messages, поэтому messages пуст , как вы правильно поняли.

Это не относится ко всем типам стандартных библиотек, поэтому будьте осторожны - некоторые контейнеры оставляют источник в «неопределенном, но допустимом» состоянии, Это означает, что безопасно выполнять с источником только те действия, которые не имеют предварительных условий. В этих случаях вы можете безопасно clear() источник, чтобы убедиться, что он пуст; clear() не имеет предварительных условий и оставляет контейнер пустым.

Гарантируется ли выполнение операций над messages до разблокировки мьютекса? Другими словами, является ли это потокобезопасным?

Да, это безопасно. Похоже, вас больше всего беспокоит код, который «захватывает» очередь сообщений.

Суть этой проблемы заключается в том, используется ли messages после уничтожения Lock. Ответ - нет, он не используется.

Построение возвращаемого значения должно завершиться до уничтожения любых локальных переменных . Зачем? Поскольку вы можете использовать локальный объект для построения возвращаемого значения!

std::vector<int> foo() {
    std::vector<int> x;
    return x;
}

x не может быть уничтожено до того, как возвращаемое значение будет построено, или существует неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...