Joshua
Joshua

Reputation: 1584

c++ multithreading function calls with parameters by reference

I am using a library which uses multithreading to call member functions when an event happens. Each "handler" in the library has a thread which can call function MyClass::Process(const Signal& signal). MyClass has a reference to a Catalog class called cat.

Inside of Process I have the following code:

Stats stats;//simple container struct to hold values

std:string id(signal.signalId());
//set values of stats here based on the values in signal

cat->onSignalUpdate(id, stats);

From the libary's documentation:

It's impossible in bounds of single instance of Handler to have two user callbacks to be invoked simultaneously. However, different instances of Handler for different channels are not linked with each other, therefore invocations from different Handler instances may occur in parallel.

Catalog has a member std::map<std::string, Stats> signal_map

Inside of Catalog::onSignalUpdate(const std::string& id, const Stats& stats)

std::map<std::string, Stats>::iterator it(signal_map.find(id));
if(it != signal_map.end())
{
    it->second = stats;
}

This works much of the time, where the proper Ids are mapped to the appropriate Stats struct. Occasionally I am getting improper matching where an ID of Handler A, is being assigned to a struct belonging to that of Handler B. It appears to me that the function is being called in parallel. I was under the impression that in threading, calls to functions, while done in parallel, are duplicated. Is this not the case, or is there an issue with passing values by reference in threads?

Upvotes: 0

Views: 646

Answers (1)

Mats Petersson
Mats Petersson

Reputation: 129434

You can't update a std::map from multiple threads without some form of protection against multiple threads modifying the map at the same time. You need a mutex or something along those lines. In partciular, if id is "new", then a the underlying data structures (typically a "RB-tree") in the map will be altered. This MUST not be done from multiple threads. You also can't access the tree to "read" while it is being modified, as the entries in the tree may be "half-updated" (e.g. the next element is pointing to an element that hasn't been properly filled in or some such).

Upvotes: 2

Related Questions