I've seen people suggest that I should wrap standard containers such as std::queue and std::vector in a mutex lock or similar if i wish to use them.
I read that as needing a lock for each individual instance of a container being accessed by multiple threads, not per type or any utilization of the c++ standard library. But this assumes that the standard containers and standard library is guaranteed to be re-entrant.
Is there such a guarantee in the language?
The standard says:
Except where explicitly specified in this standard, it is implementation-defined which functions in the Standard C++ library may be recursively reentered.
Then it proceeds to specify that a function must be reentrant in, if I count them correctly, zero cases.
If one is to strictly follow the standard in this regard, the standard library suddenly becomes rather limited in its usefulness. A huge number of library functions call user-supplied functions. Writers of these functions, especially if those are themselves released as a library, in general don't know where they will be called from.
It is completely reasonable to assume that e.g. any constructor may be called from emplace_back of any standard container; if the user wishes to eliminate any uncertainty, he must refrain from any calls to emplace_back in any constructor. Any copy constructor is callable from e.g. vector::resize or sort, so one cannot manage vectors or do sorting in copy constructors. And so on, ad libitum.
This includes calling any third party component that might reasonably be using the standard library.
All these restrictions together probably mean that a large part of the standard library cannot be used in real world programs at all.
Update: this doesn't even start taking threads into consideration. With multiple threads, at least functions that deal with containers and algorithms must be reentrant. Imagine that std::vector::operator[] is not reentrant. This would mean that one cannot access two different vectors at the same time from two different threads! This is clearly not what the standard intends. I understand that this is your primary interest. To reiterate, no, I don't think there is reentrancy guarantee; and no, I don't think absence of such guarantee is reasonable in any way. --- end update.
My conclusion is that this is probably an oversight. The standard should mandate that all standard functions must be reentrant, unless otherwise specified.
I would
completely ignore the possibility of of any standard function being non-reentrant, except when it is clear that the function cannot be reasonably made reentrant.
raise an issue with the standards committee.
[Answer left for historical purposes, but see n.m.'s answer. There's no requirement on individual functions, but there is a single global non-requirement]
Yes, the standard guarantees reentrancy of member functions of standard containers.
Let me define what (non)-reentrancy means for functions. A reentrant function can be called with well-defined behavior on a thread while it is already on the call stack of that thread, i.e. executing. Obviously, this can only happen if the control flow temporarily left the reentrant function via a function call. If the behavior is not well-defined, the function is not reentrant.
(Leaf functions can't be said to be reentrant or non-reentrant, as the flow of control can only leave a leaf function by returning, but this isn't critical to the analysis).
Example:
int fac(int n) { return n==0 ? 1 : n * fac(n-1); }
The behavior of fac(3) is to return 6, even while fac(4) is running. Therefore, fac is reentrant.
The C++ Standard does define the behavior of member functions of standard containers. It also defines all restrictions under which such behavior is guaranteed. None of the member functions of standard containers have restrictions with respect to reentrancy. Therefore, any implementation which would restrict reentrancy is non-conformant.
Related
I have trouble finding any up-to-date information on this.
Do C++11 versions of STL containers have some level of thread safety guaranteed?
I do expect that they don't, due to performance reasons. But then again, that's why we have both std::vector::operator[] and std::vector::at.
Since the existing answers don't cover it (only a comment does), I'll just mention 23.2.2 [container.requirements.dataraces] of the current C++ standard specification which says:
implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting vector<bool>, are modified concurrently.
i.e. it's safe to access distinct elements of the same container, so for example you can have a global std::vector<std::future<int>> of ten elements and have ten threads which each write to a different element of the vector.
Apart from that, the same rules apply to containers as for the rest of the standard library (see 17.6.5.9 [res.on.data.races]), as Mr.C64's answer says, and additionally [container.requirements.dataraces] lists some non-const member functions of containers that can be called safely because they only return non-const references to elements, they don't actually modify anything (in general any non-const member function must be considered a modification.)
I think STL containers offer the following basic thread-safety guarantee:
simultaneous reads of the same object are OK
simultaneous read/writes of different objects are OK
But you have to use some form of custom synchronization (e.g. critical section) if you want to do something different, like e.g. simultaneous writes on the same object.
No. Check out PPL or Intel TBB for thread safe STL-like containers.
Like others have noted they have usual "multiple reader thread safety" but that is even pre C++11. Ofc this doesnt mean single writer multiple readers. It means 0 writers. :)
There are contexts in which we want our C++ code to not perform dynamic memory allocation ('on the heap'), specifically in some embedded development use cases.
There are standard library classes which can be implemented without dynamic memory allocation: optional, array, tuple, variant to name a few.
The same is true for standard library free functions.
Are there any such classes or functions which are guaranteed by the standard to not allocate memory dynamically? The only functions I could find with such a guarantee are the placement new() functions.
There are very few cases if any where the C++ standard makes any direct guarantee about not using dynamic memory.
On systems where dynamic memory allocation is signal-unsafe, you can be certain that all functions listed as signal-safe are non-allocating. The standard mentions
_Exit
abort
forward
initializer_list functions
memcpy
memmove
move
move_if_noexcept
numeric_limits members
quick_exit
signal
type traits
plain lock-free atomic operations
If you can assume conformance to another standard, POSIX, then it lists more functions that are async-signal-safe. Some of these functions listed by POSIX are provided by C++ (and C) standards as well (such as strcat), and therefore those standard C++ functions will be signal safe on all POSIX systems.
There are a few functions in [new.delete.placement], which are non-allocating by definition.
Another question separate from guarantees is, whether a reasonable implementation of a function or a type would not allocate. Many, many things such as std::tuple and std::array (with non-allocating type arguments naturally) fall into this category.
It would be reasonable that functions which are declared noexcept, and do not have any failure path (like setting error code, returning error indicating value, or terminating the process) shouldn't allocate, since allocation may throw.
Conversely, there are functions that in a reasonable implementation do allocate dynamic memory. Obviously those that involve allocators, as well as those listed in the SO post that you linked. One non-obvious one that often bites people writing signal handlers is missing from the list: It is not at all reasonable to expect printf or any of its related functions to not allocate.
In C++17 parallel std algorithms were introduced (overloads with ExecutionPolicy arguments), where strict rules of execution order, interleaving and paralelization were defined, for example ([algorithm.parallel.exec/3]):
The invocations of element access functions in parallel algorithms invoked with an execution policy object of
type execution::sequenced_policy all occur in the calling thread of execution. [ Note: The invocations are not interleaved; see 4.6. — end note ]
(same thing in current draft)
The problem is that I can't find any such requirement for old, non-parallel overloads of these algorithms.
Question: Can this mean that library implementers can, since C++11 when thread of execution term was introduced, implement std::transform and std::generate using SIMD/multithreading/other(?)? Is there a reason for that?
[res.on.data.races]/8 Unless otherwise specified, C++ standard library functions shall perform all operations solely within the current thread if those operations have effects that are visible (4.7) to users.
This precludes any kind of behind-the-scenes multithreading that touches any user-defined entities.
I suppose, in principle, something like std::sort working on a vector<int> can prove that no user-defined class is involved, and send work to multiple threads. That's rather far-fetched, it's difficult to imagine any implementation doing this in practice.
Related to Is a static boost::wregex instance thread-safe? but for the standarized version. Can I call regex_search from several threads with the same regex object?
Claiming that std::regex is thread-safe in every respect is a pretty bold statement. The C++11 standard does not make such guarantees for the regex library.
However, looking at the prototype of std::regex_search shows that it it takes the basic_regex object as a const argument. This means that it is protected by the standard library's guarantee that the const modifier implies thread-safety of the function with respect to that argument.
In standardese, that is:
[17.6.5.9/1]
This section specifies requirements that implementations shall meet to prevent data races (1.10). Every standard library function shall meet each requirement unless otherwise specified. Implementations may prevent data races in cases other than those specified below.
[17.6.5.9/3]
A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments, including this.
So, barring a bug in the implementation of the standard library that you use, it appears that calls to std::regex_search are thread-safe with respect to the regex object that is passed in.
Other thoughts:
Just because std::regex_search is re-entrant with respect to its regex argument does not mean that you are completely out of the water. Performing an operation that modifies a regex in a non-thread-safe manner at the same time as a thread-safe call such as std::regex_search is still undefined behaviour. basic_regex's assignment operator, std::swap, and basic_regex::imbue come to mind as non-thread-safe functions with respect to the basic_regex they operate on. Knowing this, it might be better for you to make a copy of the regex object, which should come at a minimal performance cost, for each thread to use/modify at its leisure.
While Sean's answer is true of the standard, individual implementation may fall short. VC++ 2013, at least, looks like it has race conditions in its copy constructor and in a lazily evaluated variable.
I have trouble finding any up-to-date information on this.
Do C++11 versions of STL containers have some level of thread safety guaranteed?
I do expect that they don't, due to performance reasons. But then again, that's why we have both std::vector::operator[] and std::vector::at.
Since the existing answers don't cover it (only a comment does), I'll just mention 23.2.2 [container.requirements.dataraces] of the current C++ standard specification which says:
implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting vector<bool>, are modified concurrently.
i.e. it's safe to access distinct elements of the same container, so for example you can have a global std::vector<std::future<int>> of ten elements and have ten threads which each write to a different element of the vector.
Apart from that, the same rules apply to containers as for the rest of the standard library (see 17.6.5.9 [res.on.data.races]), as Mr.C64's answer says, and additionally [container.requirements.dataraces] lists some non-const member functions of containers that can be called safely because they only return non-const references to elements, they don't actually modify anything (in general any non-const member function must be considered a modification.)
I think STL containers offer the following basic thread-safety guarantee:
simultaneous reads of the same object are OK
simultaneous read/writes of different objects are OK
But you have to use some form of custom synchronization (e.g. critical section) if you want to do something different, like e.g. simultaneous writes on the same object.
No. Check out PPL or Intel TBB for thread safe STL-like containers.
Like others have noted they have usual "multiple reader thread safety" but that is even pre C++11. Ofc this doesnt mean single writer multiple readers. It means 0 writers. :)