Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are c++ standard library containers like std::queue guaranteed to be reentrant?

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?

like image 608
Max Avatar asked Jan 11 '17 00:01

Max


2 Answers

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.
like image 98
n. 1.8e9-where's-my-share m. Avatar answered Nov 15 '22 12:11

n. 1.8e9-where's-my-share m.


[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.

like image 28
MSalters Avatar answered Nov 15 '22 11:11

MSalters