Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

standard containers as local variables in multi-threaded application

I'm aware of the fact that the containers from standard library are not thread-safe. By that I used to think that a container, say of type std::list, cannot be accessed by more than one thread concurrently (some of which may modify the container). But now it seems that there is more to it than meets the eye; something more subtle, something not so obvious, well at least to me.

For example, consider this function which accepts the first argument by value:

void log(std::string msg, severity s, /*...*/) 
{
   return; //no code!
}

Is this thread-safe?

At first, it seems that it is thread-safe, as the function body accesses no shared modifiable resources, hence thread-safe. On second thought, it comes to me that when invoking such a function, an object of type std::string will be created, which is the first argument, and I think that construction of this object isn't thread-safe, as it internally uses std::allocator, which I believe isn't thread-safe. Hence invoking such a function isn't thread-safe either. But if it is correct, then what about this:

void f()
{
   std::string msg = "message"; //is it thread-safe? it doesn't seem so!
}

Am I going right? Can we use std::string (or any container which uses std::allocator internally) in multi-threaded program?

I'm specifically talking about containers as local variables, as opposed to shared objects.

I searched google and found many similar doubts, with no concrete answer. I face similar problem as his:

  • c++ allocators thread-safe?

Please consider C++03 and C++11, both.

like image 477
Nawaz Avatar asked Mar 01 '12 18:03

Nawaz


3 Answers

In C++11, std::allocator is thread safe. From its definition:

20.6.9.1/6: Remark: the storage is obtained by calling ::operator new(std::size_t)

and from the definition of ::operator new:

18.6.1.4: The library versions of operator new and operator delete, user replacement versions of global operator new and operator delete, and the C standard library functions calloc, malloc, realloc, and free shall not introduce data races (1.10) as a result of concurrent calls from different threads.

C++03 had no concept of threads, so any thread safety was implementation-specific; you'd have to refer to your implementation's documentation to see what guarantees it offered, if any. Since you're using Microsoft's implementation, this page says that it is safe to write to multiple container objects of the same class from many threads, which implies that std::allocator is thread-safe.

like image 191
Mike Seymour Avatar answered Oct 29 '22 05:10

Mike Seymour


In C++11 this would be addressed for the default allocator in:

20.6.9.1 allocator members [allocator.members]

Except for the destructor, member functions of the default allocator shall not introduce data races (1.10) as a result of concurrent calls to those member functions from different threads. Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen before the next allocation (if any) in this order.

Any user-provided allocator would have to hold to the same constraints if it were going to be used across different threads.

Of course, for earlier versions of the standard, nothing is said about this since they didn't talk about multithreading. If an implementation were to support multithreading (as many or most do), it would be responsible for taking care of those issues. Similar to the way implementations provide a thread-safe malloc() (and other library functions) for C and C++ even though the standards prior to very recently said nothing about that.

like image 5
Michael Burr Avatar answered Oct 29 '22 05:10

Michael Burr


As you may have already figured, there is not going to be an easy yes or no answer. However, I think this may help:

http://www.cs.huji.ac.il/~etsman/Docs/gcc-3.4-base/libstdc++/html/faq/index.html#5_6

I quote verbatim:

5.6 Is libstdc++-v3 thread-safe?

libstdc++-v3 strives to be thread-safe when all of the following conditions are met:

The system's libc is itself thread-safe, gcc -v reports a thread model other than 'single', [pre-3.3 only] a non-generic implementation of atomicity.h exists for the architecture in question.

like image 3
Sid Avatar answered Oct 29 '22 03:10

Sid