Это не сетевой вопрос.Это вопрос об атомарности, но сценарий окружает контекст сети.
У меня есть несколько потоков, получающих фрагменты сетевого сообщения.Каждый из них должен увеличивать атомарную переменную TotalBytesReceive
, пока не будет достигнуто значение TotalBytes
.У меня странное поведение с атомистикой, что, вероятно, связано с моим неправильным пониманием чего-либо.
В нескольких потоках:
size_t BytesReceived = // number of bytes received in this thread
bool IsMessageFinished = msg->IsMsgFinished(BytesReceived);
if(IsMessageFinished)
{do something else}
Объект msg, который является общим, содержит
class Msg
{
std::vector<char> MessageData; // The data received for the message
const size_t TotalBytes; // The final size of the complete message
std::atomic<size_t> TotalBytesReceived; // The bytes received so far
std::mutex m_mutex; // Just for testing
public:
Msg(size_t totalbytes) : TotalBytesReceived(0), TotalBytes(totalbytes)
{
MessageData.resize(TotalBytes);
}
bool IsMsgFinished(size_t BytesReceived)
{
// std::unique_lock<std::mutex> lock(m_mutex); // uncommenting fixed the problem
size_t newtotal = TotalBytesReceived += BytesReceived;
std::stringstream ss;
ss << BytesReceived << " received. New total " << newtotal << '\n';
std::cout << ss.str(); // For diagnostics
return newtotal == TotalBytes;
}
// Other functions for setting MessageData aren't important here
}
Большая проблема заключается в том, что когда несколько потоков вызывают IsMsgFinished
, мой диагностический вывод показывает, что newtotal
имеет одно и то же значение несколько раз.Это не должно быть возможно.(BytesReceived
никогда не равен 0) Есть ли здесь грубая ошибка?
Если я использую мьютекс и unique_lock в функции IsMsgFinished
, все работает отлично, но я бы не хотел использовать блокировку.