common: make 'emit_once' thread safe
By using a global in a thread-unsafe way, this logic was a barrier to
introducing multi-threading here in future. Rather than trying complicated
modifications to the logic, this change just introduces a lock around
emit_once, assuming blocking while another thread runs this function is
acceptable.
This is the first introduction of C++/C11/POSIX threading in the code base. Although C11 threads are an optional feature and POSIX threads are not guaranteed available, there are no known supported platforms lacking both. It is assumed at least one of these is usable:
┌──────────────────┬──────────────────┬────────────────────┐
│ operating system │ has C11 threads? │ has POSIX threads? │
├──────────────────┼──────────────────┼────────────────────┤
│ Cygwin │ yes │ yes │
│ Linux │ yes │ yes │
│ macOS │ │ yes │
│ MinGW │ │ yes │
│ Windows │ yes │ │
└──────────────────┴──────────────────┴────────────────────┘
A wrinkle to this is that it was discovered that cpack crashes on 32-bit
Windows in a Debug build when linking against C11 threads. The cause of this is
unknown at time of writing, but rather than debug this C++ threads have been
used on Windows instead. MSVC is guaranteed to be able to build and link C++ as
well as C. It is assumed that unconditionally using C++ threads would be
undesirable because, despite their universal availability, linking against C++’s
standard library is sometimes unwanted in Unix ecosystems.
The Autotools support follows the advice in the AX_PTHREAD docs for enabling
POSIX threads project-wide.¹ So, as odd as it looks, it is not a typo e.g.
appending $PTHREAD_CFLAGS to $CXXFLAGS.
emit_once_reset remains thread-unsafe.
¹ https://www.gnu.org/software/autoconf-archive/ax_pthread.html
If we merge this (and it’s a genuine “if”; maybe we decide the benefits of this kind of thread safety are not worth the cost of more complicated linking and threading library dependencies), we need to decide whether this constitutes a major version bump.