mardi 4 décembre 2018

C++ Atomic fetch_add

This is not a networking question. It's a question about atomics, but the scenario surrounds the context of networking.

I have several threads receiving pieces of a network message. Each is supposed to increment an atomic variable of TotalBytesReceive until the TotalBytes value has been reached. I'm having an odd behavior with atomics which is probably due to my misunderstanding of something.

Within several threads:

size_t BytesReceived = // number of bytes received in this thread
bool IsMessageFinished = msg->IsMsgFinished(BytesReceived);
if(IsMessageFinished) 
     {do something else}

The msg object which is shared contains

class Msg
{
    std::vector<char> MessageData;          // The data received for the message
    size_t TotalBytes;                      // The final size of the complete message
    std::atomic<size_t> TotalBytesReceived; // The bytes received so far

public:
    Msg() : TotalBytesReceived(0) {}

    bool IsMsgFinished(size_t BytesReceived)
    {
        size_t newtotal = TotalBytesReceived += BytesReceived;

        std::cout << newtotal; // For diagnostics

        return newtotal == TotalBytes;
    }

    // Other functions for setting TotalBytes & MessageData aren't important here
}

The big issue is that I when multiple threads call IsMsgFinished my diagnostic output is showing that newtotal has the same value multiple times. That shouldn't be possible. Is there a gross error here?

If I use a mutex and unique_lock in the IsMsgFinished function everything works great but I'd like to not use a lock.

Aucun commentaire:

Enregistrer un commentaire