简体   繁体   中英

How to initialize a C++ global mutex in a thread safe way

Trying to use a function static mutex to make code thread safe. The problem is not all compilers initialize function static variables in a thread safe way.

void Initialize()
{
  static Mutex L;   // can't be initialized at compile time because constructor calls CreateMutex()
  L.Lock()
  // call thread unsafe code
  L.Unlock()
}

Here are solutions already considered:

  1. Declare Mutex in global scope so that initialization happens before main(). Unfortunately, this doesn't work when there's a global variable whos constructor calls Initialize() because in C++ there's no guarantee about the order global variables are initialized

  2. Use atomic operations

void Initialize() { static volatile uint16_t lock=0; // trivial initialization can happen @ compile time while (AtomicExchange(lock,(uint16_t)1)!=0); // swap lock with 1 and return previous value // call thread unsafe code lock=0; }

This works but has the disadvantage of busy waiting

  1. Use pthread's compile time initializer

    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

Unfortunately, this is for Windows, and we're trying to avoid using pthread

Appreciate a solution that's portable . I know in C++ 2011, function static initialization is thread safe, but we're avoiding C++ 2011 because some embedded platforms might have unreliable C++ 2011 support.

IMO the solution to your problem is to use a nifty counter idiom. This idiom is very well described here: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter .

Using this idiom std::cout , std::cerr , std::clog streams are initialized. The only requirement is that you need to properly calculate the alignment of created type. Using that alignment you need to create a global buffer. Using that buffer the instance of the desired type with the placement new operator can be created. Boost and Modern C++ (>= C++11) have (std|boost)::aligned_storage template classes to create a properly aligned buffer for you. Please refer to:

Modern versions of C++ feature the alignof operator, which can be used to calculate the alignment of a particular type. In boost you need to use a type trait alignment_of : https://www.boost.org/doc/libs/1_69_0/libs/type_traits/doc/html/boost_typetraits/reference/alignment_of.html . alignment_of type trait is also part of STL in modern C++, but in that particular case alignof operator is simpler to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM