STL container for a single produceer single consumer FIFO? - c++

So, suppose I have a struct A { int val1; int val2};
And a std::queue<A> fifo
Two threads,
Reader thread: reads all contents from A, and clears it.
Writer thread: writes one A at a time to queue.
Is std::queue enough for maintaining a lockless thread safe fifo container with one reader and one writer? If not, can any other stl container work? dequeue is the default underlying in std::queue.

No, you absolutely cannot use any STL container directly for this. What you can use is any of the many, many lockfree queue implementations that already exist for C++. You should search for "SPSC" meaning Single Producer, Single Consumer. For example, from Boost: http://www.boost.org/doc/libs/1_59_0/doc/html/boost/lockfree/spsc_queue.html
One wait-free, fixed-size implementation is right here: SPSC lock free queue without atomics (but do note the answer and comments there, which explain some ways that the implementation in the question is not completely safe, and offer some solutions).

Related

Does a single queue with separate reader and writer threads needs locking?

I have a shared queue (implemented using a singleton queue wrapper) and a reader thread and a writer thread. I also have a mechanism to inform the reader thread when writer thread adds elements (enqueue) to the queue. Reader thread dequeue only one element when informed. Is there a necessity of a Read Write Lock in this scenario.
Since writer is only enqueing and reader dequeing I feel like there is no need for a lock, if reader checks the queue size when dequeing.
Since writer is only enqueing and reader dequeing I feel like there is no need for a lock, if reader checks the queue size when dequeing.
Among other problems that operation alone is already unsafe, when the queue is modified by another thread. In c++, any unsynchronized access to a non-atomic shared variable (with at least one of them is a write) is a data race and hence UB.
I assume you mean a stl::queue and no most operations on stl containers are not thread save. For an discussion on exceptions see C++11 STL containers and thread safety. STL prefers speed over security (e.g. range check for array indices etc.) assuming that developers will implement their own checks.

Is erasing and inserting in a single linked list thread safe?

Using std::forward_list are there any data races when erasing and inserting? For example I have one thread that does nothing but add new elements at the end of the list, and I have another thread that walks the (same) list and can erase elements from it.
From what I know of linked lists, each element holds a pointer to the next element, so if I erase the last element, at the same time that I am inserting a new element, would this cause a data race or do these containers work differently (or do they handle that possibility)?
If it is a data race, is there a (simple and fast) way to avoid this? (Note: The thread that inserts is the most speed critical of the two.)
There are thread-safety guarantees for the standard C++ library containers but they tend not to be of the kind people would consider thread-safety guarantees (that is, however, an error of people expecting the wrong thing). The thread-safety guarantees of standard library containers are roughly (the relevant section 17.6.5.9 [res.on.data.races]):
You can have as many readers of a container as you want. What exactly qualifies as reader is a bit subtly but roughly amounts to users of const member functions plus using a few non-const members to only read the data (the thread safety of the read data isn't any of the containers concern, i.e., 23.2.2 [container.requirements.dataraces] specifies that the elements can be changed without the containers introducing data races).
If there is one writer of a container, there shall be no other readers or writes of the container in another thread.
That is, reading one end of a container and writing the other end is not thread safe! In fact, even if the actual container changes don't affect the reader immediately, you always need synchronization of some form when communicating a piece of data from one thread to another thread. That is, even if you can guarantee that the consumer doesn't erase() the node the producer currently insert()s, there would be a data race.
No, neither forward_list nor any other STL containers are thread-safe for writes. You must provide synchronization so that no other threads read or write to the container while a write is occurring. Only simultaneous reads are safe.
The simplest way to do this is to use a mutex to lock access to the container while an insert is occurring. Doing this in a portable way requires C++ 11 (std::mutex) or platform-specific features (mutexes in Windows, perhaps pthreads in Linux/Unix).
Unless you're using a version of the STL that explicitly states it is thread-safe then no, the containers are not thread safe.
It's rare to make general purpose containers thread safe by default, as it imposses a performance hit on users who don't require thread safe access to the container, and this is by far the normal usage pattern.
If thread safety is an issue for you then you'll need to surround your code with locks, or use a data structure that is designed specifically designed for multi threaded access.
std containers are not meant to be thread safe.
You should carefully protect them for modify operations.

Locked write, unlocked read

Algorithmic question
How to allow only the following types of threaded operations on an object?
multiple simultaneous reads, no writes
single write, no reads
Example: wrapper for STL container allowing efficient search from multiple threads. For simplicity, let assume no iterator can be accessed from outside of the wrapper in question.
Let's assume we have semaphores and mutexes at out disposal.
I know that boost libraries has this concept implemented. I'd like to understand how is this usually done.
Use boost::shared_mutex to handle frequent read, infrequent write access patterns.
As you've noted, STL containers are 'leaky' in that you can retrieve an iterator which has to be treated as either an implicit ongoing operation for write (if non-const) or read (if const), until the iterator goes out of scope. Writes to the container by other threads while you hold such an iterator can invalidate it. Your wrapper would have to be carefully designed to handle this case and keep the wrapper class efficient.
You want a "multiple-reader / single-writer" mutex : Boost.Thread provides one.

Thread safety for STL queue

I am using a queue to communicate between threads. I have one reader and multiple writer threads. My question is do I need to lock the queue every time when I use push/front/pop from the queue for the reader? Can I do something like the following:
//reader threads
getLock();
get the number of elements from the queue
releaseLock();
int i = 0;
while( i < numOfElements){
queue.front();
queue.pop();
i++
}
The idea is that I want to reduce the granularity of the locked code and since the writer thread would only write to the back of the queue and there is only a single reader thread. As long as I get the number of elements, then I could get the elements from the queue OR do I need to enclose the front() and pop() in the lock as well?
As others have already mentioned, standard containers are not required to guarantee thread safety so what you're asking for cannot be implemented portably. You can reduce the time your reader thread is locking the writers out by using 2 queues and a queue pointer that indicates the queue that is currently in use by the writers.
Each writer would:
Acquire lock
Push element(s) into the queue currently pointed to by the queue pointer
Release lock
The reader can then do the following:
Acquire lock
Switch queue pointer to point to the second queue
Release lock
Process elements from the first queue
Any type that doesn't explicitly state its thread-safety guarantees should always be controlled by a mutex. That said, your implementation's stdlib may allow some variation of this — but you can't know for all implementations of std::queue.
As std::queue wraps another container (it's a container adapter), you need to look at the underlying container, which defaults to deque.
You may find it easier, better, or more portable to write your own container adapter that makes the guarantees you need. I don't know of anything that does this exactly for a queue in Boost.
I haven't looked at C++0x enough to know if it has any solution for this out-of-the-box, but that could be another option.
This is absolutely implementation-dependent. The C++ standard makes no mention about threads or thread safety, so whether or not this will work depends on how your implementation handles queue elements.
In your case, the reader is actually popping the queue, which is considered a write operation. I doubt any of the common implementations actually guarantee thread-safety in this case, when multiple threads simultaneously write to a container. At least VC++ does not:
For reads to the same object, the object is thread safe for reading when no writers on other threads.
For writes to the same object, the object is thread safe for writing from one thread when no readers on other threads.
Sometimes you can resolve a lot of concurrency headache by avoiding sharing state or resources among threads. If you have multiple threads that access a container concurrently in order to push in their work then try to have them work on dedicated containers. At specific points you then collect the containers' elements onto the central container in a non-concurrent manner.
If you can avoid sharing state or resources among threads then you have no problem running threads concurrently. Threads then need not worry about each other, because they are completely isolated and bear no effect whatsoever on each other.
Your hunch is correct: Even though you cannot count on STD queue to be thread safe, a queue should be thread safe by design.
A nice explanation of why that is the case and a standard implementation of thread safe, lock free queues in C++ is given by van Dooren

Do I need to lock STL list with mutex in push_back pop_front scenario?

I have a thread push-backing to STL list and another thread pop-fronting from the list. Do I need to lock the list with mutex in such case?
From SGI's STL on Thread Safety:
If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.
Since both your threads modify the list, I guess you have to lock it.
Most STL implementations are thread safe in the sens that you can access several instances of a list type from several threads without locking. But you MUST lock when you are accessing the same instance of your list.
Have a look on this for more informations : thread safty in sgi stl
Probably. These operations are not simple enough to be atomic, so they'll only be thread-safe if the implementation explicitly performs the necessary locking.
However, the C++ standard does not specify whether these operations should be thread-safe, so it is up to the individual implementation to decide that. Check the docs. (Or let us know which implementation you're using)
There is no guarantee that a STL implementation is thread-safe, and since it costs performance I would guess that most aren't. You should definitely use a mutex.
Since the stl pop / push operations are AFAIK non-atomic you do have to use a mutex.