Я пытаюсь избежать гонки данных в почтовом ящике Vector. В моей программе (для задания) есть классы/объекты Deliverer, Recipient и Letter. Deliverer и Recipient выполняются в потоках, а Deliverer должен передавать Letter-объекты (или, скорее, указатели на них) различным объектам-Receiver. Для этого у каждого Получателя есть член std::vector почтовый ящик, куда Deliverer помещает свои письма. Получатель регулярно проверяет почтовый ящик в отдельном потоке, отсюда и возможность гонки данных, которой я хочу избежать.
Существует также LogicisticsCenter, который генерирует письма и распределяет их среди Доставщиков. Как только доставщик достигает полной емкости писем, LogisticCenter уведомляет об этом Доставщика (через условие_переменной), который затем отправляется для доставки писем. Это также работает с мьютексами.
Проблема:
Сначала я использовал lock_guard с вектором почтового ящика, что привело к ошибке bad_alloc, что привело к сбою программы. После некоторого тестирования я обнаружил, что создание новой переменной Vector в Recipient.h без удаления старой решает проблему (следовательно, mailbox6< /code> в коде). Однако выполнение любого из следующих действий приводит к сбою программы:
- Использование mailbox вместо mailbox6 в Recipient.cpp
- Изменение имени почтового ящика на другое, например test, и использование его вместо mailbox6 в Recipient.cpp
Изменение порядка векторного почтового ящика и векторного почтового ящика6 в Recipient.h
< li>Удаление строкового почтового ящика Vector из Recipient.h - Замена почтового ящика Vector на char dummy code> в Recipient.h
Был также способ вызвать сбой с новой переменной, но я сейчас не могу его вспомнить. Дополню правку, как только вспомню.
- Та же проблема происходит с помощью mtx.lock()/mtx.unlock(), lock_guard и unique_lock
- Я использую Visual Studio Code в Windows 11; код выполняется в WSL (Ubuntu 22.04.4 LTS)
- Некоторые методы или переменные не используются (например, bool WantToBeRung); они предназначены для предстоящих задач назначения.
- Я успешно использовал мьютексы / unique_lock в другой части этой программы: когда заставлял Доставщика ждать заполнения буквами для доставки через логистический центр
TL;DR:Пытаемся избежать гонки данных с помощью мьютекса и lock_guard; программа аварийно завершает работу при вызове std::vector.push_back если этот вектор либо вызывал сбой раньше, либо имеет то же имя, что и вектор, который это сделал, либо находится в том же диапазоне памяти внутри объекта Receiver как вектор, который выполнял
Код (это весь код проекта)
Recipient
#ifndef RECIPIENT_H#define RECIPIENT_H
#include
#include
#include
#include "letter.h"
using namespace std;
class Recipient {
private:
int id;
bool wantsToBeRung;
mutable mutex mtx; // unable to return mutex in getMutex() properly without mutable
mutable condition_variable condition;
vector mailbox;
vector mailbox6;
vector receivedLetters;
void mainLoop();
vector getMail();
void stashMail(vector letters);
public:
Recipient();
~Recipient();
void init();
void ring();
void deliverLetter(Letter* letter);
void print(string text);
int getId();
mutex* getMutex() const;
condition_variable* getConditionVariable() const;
};
#endif
#include "recipient.h"
#include
#include
Recipient::Recipient() {
static int idCounter = 0;
id = idCounter++;
}
Recipient::~Recipient() {
}
void Recipient::init() {
print("Yar");
usleep(1000 * 1000 * 3);
//mainLoop();
}
void Recipient::mainLoop() {
while (true) {
print("Checking mail");
//vector letters = getMail();
//stashMail(letters);
sleep(5);
}
}
void Recipient::deliverLetter(Letter* letter) {
unique_lock locker(mtx); // CAUSES std::bad_alloc when accessing mailbox
//mtx->lock();
mailbox6.push_back(letter);
//mtx->unlock();
}
vector Recipient::getMail() {
unique_lock locker(mtx); // prevent simultaneous adding & removing of letters
vector letters = mailbox6;
//mtx->lock();
mailbox6.clear();
//mtx->unlock();
return letters;
}
void Recipient::stashMail(vector letters) {
for (auto it = letters.begin(); it != letters.end(); it++) {
receivedLetters.push_back(*it);
}
}
void Recipient::print(string text) {
cout
Подробнее здесь: https://stackoverflow.com/questions/786 ... mutex-lock