I’m aware, that I need to use mutex, when I perform operations on single STL container inside multiple threads. However I want to know if there are any exceptions from this rule. Please consider simplified scenario I’m trying to implement.
I have multiple threads adding elements to container and operation is surrounded with mutex lock/unlock. Then threads notify somehow (e.g. using eventfd on linux) single thread dedicated to dispatch elements in this container. What I want to do is to access first element in container without using mutex. Sample code based on deque but note that I ca use any container with queue capability:
std::mutex locker;
std:deque<int> int_queue;
int fd; // eventfd
eventfd_t buffer;
bool some_condition;
Thread 1, 2, 3, etc.
locker.lock ();
int_queue.push_back (1);
locker.unlock ();
eventfd_write (fd, 1);
Thread dedicated to dispatch elements:
while (true)
{
bool some_condition (true);
locker.lock ();
if (int_quque.empty () == false)
{
locker.unlock ();
}
else
{
locker.unlock ();
eventfd_read (fd, &buffer);
}
while (some_condition)
{
int& data (int_queue.front ());
some_condition = some_operation (data); // [1]
}
locker.lock ();
int_queue.pop ();
locker.unlock ();
}
[1] I will do some_operation() on signle element many times, that’s why I want to avoid mutex locking here. It’s to expensive.
I want to know if this code can lead to any synchronisation problems or something.
What you need is reference stability. I.e. you can use containers this way if the reference to the first element is not invalidated when the container is push_back’d. And even then, you’ll want to obtain the reference to the front element under the lock.
I’m more familiar with
std::condition_variablefor the event notification, so I’ll use that:23.3.3.4 [deque.modifiers] says this about
push_back:That is the key to allowing you to hang onto that reference outside of the lock. If
thread_1_2_3starts inserting or erasing in the middle, then you can no longer hang on to this reference.You can’t use a
vectorthis way. But you could use alistthis way. Check each container you want to use this way for reference stability.