[libcxxabi] Added convenience classes to cxa_guard

This is the 5th of 5 changes to overhaul cxa_guard.
See D108343 for what the final result will be.

Depends on D115368

Reviewed By: ldionne, #libc_abi

Differential Revision: https://reviews.llvm.org/D115369
This commit is contained in:
Daniel McIntosh 2021-12-08 13:22:52 -05:00
parent 29be7c9c4f
commit f011a53c14
2 changed files with 33 additions and 18 deletions

View File

@ -589,6 +589,26 @@ public:
}
};
//===----------------------------------------------------------------------===//
// Convenience Classes
//===----------------------------------------------------------------------===//
/// NoThreadsGuard - Manages initialization without performing any inter-thread
/// synchronization.
using NoThreadsGuard = GuardObject<InitByteNoThreads>;
/// GlobalMutexGuard - Manages initialization using a global mutex and
/// condition variable.
template <class Mutex, class CondVar, Mutex& global_mutex, CondVar& global_cond,
uint32_t (*GetThreadID)() = PlatformThreadID>
using GlobalMutexGuard = GuardObject<InitByteGlobalMutex<Mutex, CondVar, global_mutex, global_cond, GetThreadID>>;
/// FutexGuard - Manages initialization using atomics and the futex syscall for
/// waiting and waking.
template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = PlatformFutexWake,
uint32_t (*GetThreadIDArg)() = PlatformThreadID>
using FutexGuard = GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>>;
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
@ -605,23 +625,20 @@ enum class Implementation { NoThreads, GlobalMutex, Futex };
template <Implementation Impl>
struct SelectImplementation;
/// Manage initialization without performing any inter-thread synchronization.
template <>
struct SelectImplementation<Implementation::NoThreads> {
using type = GuardObject<InitByteNoThreads>;
using type = NoThreadsGuard;
};
/// Manage initialization using a global mutex and condition variable.
template <>
struct SelectImplementation<Implementation::GlobalMutex> {
using type = GuardObject<InitByteGlobalMutex<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>>;
using type = GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
GlobalStatic<LibcppCondVar>::instance, PlatformThreadID>;
};
/// Manage initialization using atomics and the futex syscall for waiting and waking.
template <>
struct SelectImplementation<Implementation::Futex> {
using type = GuardObject<InitByteFutex<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>>;
using type = FutexGuard<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
};
// TODO(EricWF): We should prefer the futex implementation when available. But

View File

@ -119,14 +119,13 @@ int main(int, char**) {
{
#if defined(_LIBCXXABI_HAS_NO_THREADS)
static_assert(CurrentImplementation == Implementation::NoThreads, "");
static_assert(std::is_same<SelectedImplementation, GuardObject<InitByteNoThreads>>::value, "");
static_assert(std::is_same<SelectedImplementation, NoThreadsGuard>::value, "");
#else
static_assert(CurrentImplementation == Implementation::GlobalMutex, "");
static_assert(
std::is_same<SelectedImplementation,
GuardObject<InitByteGlobalMutex<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
GlobalStatic<LibcppCondVar>::instance>>>::value,
"");
static_assert(std::is_same<SelectedImplementation,
GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
GlobalStatic<LibcppCondVar>::instance>>::value,
"");
#endif
}
{
@ -139,17 +138,16 @@ int main(int, char**) {
}
}
{
Tests<uint32_t, GuardObject<InitByteNoThreads>>::test();
Tests<uint64_t, GuardObject<InitByteNoThreads>>::test();
Tests<uint32_t, NoThreadsGuard>::test();
Tests<uint64_t, NoThreadsGuard>::test();
}
{
using MutexImpl =
GuardObject<InitByteGlobalMutex<NopMutex, NopCondVar, global_nop_mutex, global_nop_cond, MockGetThreadID>>;
using MutexImpl = GlobalMutexGuard<NopMutex, NopCondVar, global_nop_mutex, global_nop_cond, MockGetThreadID>;
Tests<uint32_t, MutexImpl>::test();
Tests<uint64_t, MutexImpl>::test();
}
{
using FutexImpl = GuardObject<InitByteFutex<&NopFutexWait, &NopFutexWake, &MockGetThreadID>>;
using FutexImpl = FutexGuard<&NopFutexWait, &NopFutexWake, &MockGetThreadID>;
Tests<uint32_t, FutexImpl>::test();
Tests<uint64_t, FutexImpl>::test();
}