Is Std::String Thead-Safe with Gcc 4.3

Is std::string thead-safe with gcc 4.3?

Threads are not yet part of the standard. But I don't think that any vendor can get away without making std::string thread-safe, nowadays. Note: There are different definitions of "thread-safe" and mine might differ from yours. Of course, it makes little sense to protect a container like std::vector for concurrent access by default even when you don't need it. That would go against the "don't pay for things you don't use" spirit of C++. The user should always be responsible for synchronization if he/she wants to share objects among different threads. The issue here is whether a library component uses and shares some hidden data structures that might lead to data races even if "functions are applied on different objects" from a user's perspective.

The C++0x draft (N2960) contains the section "data race avoidance" which basically says that library components may access shared data that is hidden from the user if and only if it activly avoids possible data races. It sounds like a copy-on-write implementation of std::basic_string must be as safe w.r.t. multi-threading as another implementation where internal data is never shared among different string instances.

I'm not 100% sure about whether libstdc++ takes care of it already. I think it does. To be sure, check out the documentation

std::string in a multi-threaded program

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

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

std::string messed up when using it as storage within (boost.)async_read_some

Well, the problem wasn't Boost nor Boost::Asio. It was the method how I tested my application:

I used nc (Netcat) to test the performance and functions of my application with this command

nc localhost 4450 <testfile

where testfile contained a 36 characters long test string. Netcat wasn't only slow - it was the origin of this problem.

After I changed my strategy and coded a little boost::asio application to send the same requests to my application it worked. Fast, easy and without any problems.

I learned my lesson: Never use Netcat for stress tests again!

Return the Reference of a pass-by-reference parameter

Do not use a reference parameter to store output.

Simply create a local std::string inside the function and return it by value.

std::string  toHexString( const uint8_t *buf, uint32_t size ) 
{
std::string out;
// modify 'out'
return out;
}

Due to compiler techniques such as Return Value Optimization, this should have similar performance, but much better semantics(no need for dummy extra parameter).

As far as thread safety goes the function is probably fine. You only need to worry about thread safety when data is shared between threads, and this function should not share any data.

How can I deploy a C++11 program (with dependencies) on CentOS 6, whose GCC is C++03?

Actually, you can distribute a program compiled with a newer g++ compiler on a vanilla CentOS 6 platform. There are several ways to do this: The easiest is to use the DevToolset 3, which will give you g++ 4.9.2 (the dev toolset 2 will give you gcc 4.8.2). Then, just compile your application with this g++. When distributing your software, you need to make sure to also ship the libstdc++.so that is being shipped with g++ 4.9. Either set the LD_LIBRARY_PATH so it gets picked up on startup, or set the RPATH to tell your executable where to look first for libraries.

Essentially, you can do this also with newer compilers, but then you first need to compile the compiler itself. If you don't want to compile a compiler first, go with a respective dev toolset and you should be fine.

Yes, you can also try to statically link libstdc++.a. Search for the option -static-libstdc++:

When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

But if you statically link, you will not get any security updates etc. Granted, you will not get the updates, if you ship libstdc++.so on your own as well, but incremental updates maybe easier.

And with respect to running your application: The rule of thumb is: Compile on the oldest platform you need to support, then your binaries (with self-shipped libstdc++ and other required libs) will likely work also on newer versions. That is, if you compile on CentoOS 6, and it works, then you can expect it to also work on CentOS 7. On a related subject, this is exactly the reason why for instance AppImage and related solutions recommend to build on an old system.

Why does c++ std::hash create a functor struct and can it be called without creating a struct each time

but I don't understand the actual reason a functor is even necessary in this context.

There is a good reasons why std::hash is a functor and not a function and that is that it can have state. The C++ standard allows for salted hashes so that each execution of the same program can create different hashed values for the same original value.

Is it safe / correct to create one hash struct then call its operator() multiple different times?

std::hash<std::string> strHash;
strHash(data1);
strHash(data2);

Yes, that code is safe. You don't need to construct a hash every time you want to hash something. It's okay to create a single hash object and use that for all of the hashes you need (in a singly threaded environment).

Is re-using one hash struct going to be threadsafe? And if not, how would I make it more threadsafe?

Depends on the use but most likely not. std::hash has no thread safety guarantees so you need to protect the access to it using a mutex or some other synchronization technique. Or you could just use one hash object per thread as they are required to give the same output for the same input. This gives you a little extra space overhead but now you don't have any synchronization overhead which could be costly.

QT 4.3 passing class pointer between threads

"Does QT perform atomic operations on this class if it is composed of native types" - the language is C++, Qt just a library. Thus Qt doesn't do any magic when variables are accessed from multiple threads and the usual C++ multithreading rules and its memory model (since C++11) apply. The signal/slot mechanism however implements a message passing mechanism for inter-thread communication: Queued connections (see also the page on thread synchronisation) pass the arguments from one thread to another by copying them. I.e., passing value types such as QString, int, double is safe - the receiving thread will operate on a copy of the sending thread's data and there's no concurrent access that'd need locking. Signal/Slot arguments passed by const reference will also be copied by the signal/slot system.

However, if you pass pointers either as argument or contained in a struct, the pointer is copied, not the object it points to (in the case there's no custom copy ctor/assignment operator implementation doing otherwise). Thus, accessing the passed pointer is not safe for the and you'd need a synchronisation mechanism such as a mutex.

In your example, PORT_CHECK_STRUCT *portCheck has this problem (when passing a PortInfo object), as well as void COM_DATA_UPDATE(const U_BYTE* msg). I'd suggest to pass the data via std::array (or std::vector/QVector if you can't use C++11).

Creating a class to store threads and calling them

The problem here is that you do not wait for the threads to end. In main you create c. This then spawns the threads. The next thing to happen is to return which destroys c. When c is destroyed it destroys its members. Now when a thread is destroyed if it has not been joined or detached then std::terminate is called and the program ends

What you need to do is in the destructor, set running to false and then call join on both the threads. This will stop the loop in each thread and allow c to be destructed correctly.

Doing this however brings up another issue. running is not an atomic variable so writing to it while threads are reading it is undefined behavior. We can fin that though by changing running to a std::atomic<bool> which provides synchronization.

I also had to make a change to the thread construction. When you want to use a member function the syntax should be

std::thread(&class_name::function_name, pointer_to_instance_of_class_name, function_parameters)

so in this case it would be

threads.push_back(std::thread(&client::main, this));
threads.push_back(std::thread(&client::render, this));

Communication between threads via shared vector

std data structures are not thread safe (for the most part) and therefore require additional synchronization if accessed by multiple threads simultaneously. In your case, one thread could be calling push_back while another thread is calling erase. This will produce undefined behavior. To fix this, both the push_back and the erase need to be protected by the same lock. I recommend you google for thread safety in the c++ standard library and read more about it.


Also, using a vector here is probably not the best choice. You should look into std::queue instead. When you erase the first element of the vector is has to copy all of the strings later in the vector down one, which can be very expensive. queue does not suffer from this problem.



Related Topics



Leave a reply



Submit