Background: I create many small utilities for some very specialised data processing. Often, I am the only user. I don't even think about multi-threaded programming, because the run-time performance is by far sufficient for my use cases. The critical resource is my programming time. So I want to avoid any extra effort required for multi-threaded programming.
However, it seems there is a risk, that my source code gets executed in a multi-threaded context, when I reuse my code in future.
According to CppCoreGuidelines :
Be careful: there are many examples where code that was “known” to never run in a multi-threaded program was run as part of a multi-threaded program. Often years later. Typically, such programs lead to a painful effort to remove data races. Therefore, code that is never intended to run in a multi-threaded environment should be clearly labeled as such and ideally come with compile or run-time enforcement mechanisms to catch those usage bugs early.
Most of the suggestions in the same source actually get me started with multi-threaded programming. The one suggestion, which I prefer to follow says:
Refuse to build and/or run in a multi-threaded environment.
So my question is, how do I do that? E.g. is there an include file, #pragma or so to ensure single threaded build / execution of everything within a source file?
With g++
/gcc
compiling and linking multithreaded code requires using -pthread
compiler and linker option. This option sets _REENTRANT
macro which you can inspect at compile time:
$ c="g++ -E -dD -xc++ /dev/null"
$ diff <($c) <($c -pthread)
389a390
> #define _REENTRANT 1
Contrary to popular belief, using -lpthread
linker option is unnecessary and insufficient to correctly build a multi-threaded program.
Microsoft Visual Studio sets _MT
macro for a multi-threaded build, IIRC.
Boost library does the following:
// Turn on threading support if the compiler thinks that it's in
// multithreaded mode. We put this here because there are only a
// limited number of macros that identify this (if there's any missing
// from here then add to the appropriate compiler section):
//
#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \
|| defined(_PTHREADS) || defined(__APPLE__) || defined(__DragonFly__)) \
&& !defined(BOOST_HAS_THREADS)
# define BOOST_HAS_THREADS
#endif
So that you can #include <boost/config.hpp>
and then inspect the value of BOOST_HAS_THREADS
macro.
The following causes a compilation error if it is built in multi-threaded mode:
#if defined(BOOST_HAS_THREADS) || defined(_REENTRANT) || defined(_MT)
#error This code is single-threaded only.
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With