[ACCEPTED]-std::string in a multi-threaded program-stl

Accepted answer
Score: 11

You cannot safely and portably do anything 29 in a multi-threaded program. There is no 28 such thing as a portable multi-threaded 27 C++ program, precisely because threads throw 26 everything C++ says about order of operations, and 25 the results of modifying any variable, out 24 the window.

There's also nothing in the standard 23 to guarantee that vector can be used in the way 22 you say. It would be legal to provide a 21 C++ implementation with a threading extension 20 in which, say, any use of a vector outside 19 the thread in which it was initialized results 18 in undefined behavior. The instant you start 17 a second thread, you aren't using standard 16 C++ any more, and you must look to your 15 compiler vendor for what is safe and what 14 is not.

If your vendor provides a threading 13 extension, and also provides a std::string 12 with COW that (therefore) cannot be made 11 thread-safe, then I think for the time being 10 your argument is with your vendor, or with 9 the threading extension, not with the C++ standard. For 8 example, arguably POSIX should have barred 7 COW strings in programs which use pthreads.

You 6 could possibly make it safe by having a 5 single mutex, which you take while doing 4 any string mutation whatsoever, and any 3 reads of a string that's the result of a 2 copy. But you'd probably get crippling contention 1 on that mutex.

Score: 8

You are right. This will be fixed in C++0x. For 6 now you have to rely on your implementation's 5 documentation. For example, recent libstdc++ Versions 4 (GCC) lets you use string objects as if no string 3 object shares its buffer with another one. C++0x 2 forces a library implemetation to protect 1 the user from "hidden sharing".

Score: 7

Given that the standard doesn't say a word 6 about memory models and is completely thread 5 unaware, I'd say you can't definitely assume 4 every implementation will be non-cow so 3 no, you can't

Apart from that, if you know 2 your tools, most of the implementations 1 will use non-cow strings to allow multi-threading.

Score: 4

You can use STLport. It provides non-COW 24 strings. And it has the same behavior on 23 different platforms.

This article presents comparison 22 of STL strings with copy-on-write and noncopy- on-write 21 argorithms, based on STLport strings, ropes 20 and GNU libstdc++ implementations.

In a company 19 where I work I have some experience running 18 the same server application built with STLport 17 and without STLport on HP-UX 11.31. The 16 application was compiled with gcc 4.3.1 15 with optimization level O2. So when I run 14 the progrma built with STLport it processes 13 requests 25% faster comparing to the the 12 same program built without STLport (which 11 uses gcc own STL library).

I profiled both 10 versions and found out that the version 9 without STLport spends much more time in 8 pthread_mutex_unlock() (2.5%) comparing to the version with STLport 7 (1%). And pthread_mutex_unlock() itself in the version without 6 STLport is called from one of std::string 5 functions.

However, when after profiling 4 I changed assignments to strings in most 3 often called functions in this way:

string_var = string_var.c_str(); // added .c_str()

there 2 was significant improvement in performance 1 of the version without STLport.

Score: 4

A more correct way to look at it would be 14 "You cannot safely and portably use C++ in 13 a multithreaded environment". There is no 12 guarantee that other data structures will 11 behave sensibly either. Or that the runtime 10 won't blow up your computer. The standard 9 doesn't guarantee anything about threads.

So to do 8 anything with threads in C++, you have to rely on 7 implementation-defined guarantees. And Then 6 you can safely use std::string because each implementation 5 tells you whether or not it is safe to use 4 in a threaded environment.

You lost all hope 3 of true portability the moment you spawned 2 a second thread. std::string isn't "less portable" than 1 the rest of the language/library.

Score: 1

In MSVC, std::string is no longer reference 4 counted shared pointer to a container. They 3 choose to the entire contents by-value in 2 every copy constructor and assignment operator, to 1 avoid multithreading problems.

Score: 0

I regulate the string access:

  • make std::string members private
  • return const std::string& for getters
  • setters modify the member

This has always 1 worked fine for me and is correct data hiding.

Score: 0

If you want to disable COW semantics, you 4 could force your strings to make copies:

// instead of:
string newString = oldString;

// do this:
string newString = oldString.c_str();

As 3 pointed out, especially if you could have 2 embedded nulls, then you should use the 1 iterator ctor:

string newString(oldString.begin(), oldString.end());

More Related questions