Added a configure test for pthread_cond_clockwait presence. If it is
available, use it for timed waits with absolute timeouts on POSIX platforms.
Futex-based implementation has been improvved to use proper atomic operations
to access m_cond, which is needed to avoid races between the futex syscall and
our notifying operations. Also, check if m_cond has changed whil looping in
the waiting operations.
We are going to use more C++11 features unconditionally, so add more
requirements in the build files. Don't straight require cxx11 in the
Jamfile as this eliminates all versions of MSVC from the builds.
Also remove older compilers that don't support enough of C++11 from CI.
Windows SDK headers in MinGW-w64 define _WIN32_WINNT to _WIN32_WINNT_WS03
by default, which prevents Boost.WinAPI from applying its own default.
This disables the WaitOnAddress API that is now required by Boost.Atomic.
Define _WIN32_WINNT to 0x0A00 ourselves on this platform (which is
the highest supported value anyway) to avoid breaking downstream libraries.
Refs https://github.com/boostorg/atomic/issues/73.
This makes WaitOnAddress/WakeByAddressSingle/WakeByAddressAll a mandatory
requirement. Thus, runtime detection of these APIs is now removed.
Also, linking with synchronization lib on Windows is now mandatory. The
library provides WaitOnAddress & co. which are now mandatory.
When targeting Windows 8, the always_has_native_wait_notify static constant
would be set to false even though the native implementation of waiting
and notifying operations through WaitOnAddress would always be used.
To fix this, moved direct WaitOnAddress & co. usage to public header. This
also requires users to link with synchronization.lib, which is done
automatically on compilers that support auto-linking.
The compiled library still implements runtime detection of WaitOnAddress,
even when building for Windows 8 and later. This allows user's code to
be later compiled for Windows 7 and older and still work. This code is
not used when user's code targets Windows 8 or later.
As part of this refactoring, renamed has_synchronization test and
related CMake variable to better communicate that we're testing for
a library.
In order to avoid hardcoding library dependencies recursively for the
configure checks performed in CMake build scripts, we generate the list
of all include directories. If there is a unified Boost include tree,
we can use that and avoid filesystem scanning.
Since Boost.Atomic may require linking with pthreads, set up
multithreading compiler flags and add a formal dependency on
the threading library in CMakeLists.txt.
We need to explicitly link with synchronization.lib when the
WaitOnAddress API is enabled at compile time for ARM targets. Since
this library is only available on newer Windows SDKs, we have to perform
a configure check for whether it is available.
The user may define BOOST_ATOMIC_LOCK_POOL_SIZE_LOG2 macro to specify
binary logarithm of the size of the internal lock pool. The macro
only has effect when building Boost.Atomic.
The generic implementation is based on the lock pool. A list of condition
variables (or waiting futexes) is added per lock. Basically, the lock
pool serves as a global hash table, where each lock represents
a bucket and each wait state is an element. Every wait operation
allocates a wait state keyed on the pointer to the atomic object. Notify
operations look up the wait state by the atomic pointer and notify
the condition variable/futex. The corresponding lock needs to be acquired
to protect the wait state list during all wait/notify operations.
Backends not involving the lock pool are going to be added later.
The implementation of wait operation extends the C++20 definition in that
it returns the newly loaded value instead of void. This allows the caller
to avoid loading the value himself.
The waiting/notifying operations are not address-free. Address-free variants
will be added later.
Added tests for the new operations and refactored existing tests for atomic
operations. Added docs for the new operations.
Increased lock pool size to 64 entries and improve pool efficiency:
- Shift off lower pointer bits that are zero due to object alignment.
- Mix higher pointer bits to account for alignment typically imposed by
malloc/new implementations.
- Use bit masking to select a lock from pool, given that the pool size
is a power of 2 now.
Also, extracted (u)intptr_t definition to a common header to avoid code
duplication.
Generate cmake target that builds the library and which can
be used by other libraries to express their dependency on
this library and retrieve any configuration information
such as the include directory, binary to link to,
transitive dependencies, necessary compiler options or the
required C++ standards level.