`<condition_variable>`: Avoid squirrelly forward declaration of `_Cnd_internal_imp_t` (#4545)

This commit is contained in:
Stephan T. Lavavej 2024-04-09 13:59:17 -07:00 коммит произвёл GitHub
Родитель d3c435b3d1
Коммит 29b30dfb3b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 36 добавлений и 56 удалений

Просмотреть файл

@ -33,50 +33,38 @@ struct _Stl_critical_section {
};
struct _Mtx_internal_imp_t {
#if defined(_CRT_WINDOWS) || defined(UNDOCKED_WINDOWS_UCRT)
#ifdef _WIN64
static constexpr size_t _Critical_section_size = 16;
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
static constexpr size_t _Critical_section_size = 8;
#endif // ^^^ !defined(_WIN64) ^^^
#else // ^^^ Windows private STL / public STL vvv
#ifdef _WIN64
#if defined(_CRT_WINDOWS) || defined(UNDOCKED_WINDOWS_UCRT) // for Windows-internal code
static constexpr size_t _Critical_section_size = 2 * sizeof(void*);
#elif defined(_WIN64) // ordinary 64-bit code
static constexpr size_t _Critical_section_size = 64;
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
#else // vvv ordinary 32-bit code vvv
static constexpr size_t _Critical_section_size = 36;
#endif // ^^^ !defined(_WIN64) ^^^
#endif // ^^^ public STL ^^^
static constexpr size_t _Critical_section_align = alignof(void*);
#endif // ^^^ ordinary 32-bit code ^^^
int _Type{};
union {
_Stl_critical_section _Critical_section{};
_STD _Aligned_storage_t<_Critical_section_size, _Critical_section_align> _Cs_storage;
_STD _Aligned_storage_t<_Critical_section_size, alignof(void*)> _Cs_storage;
};
long _Thread_id{};
int _Count{};
};
// Size and alignment for _Cnd_internal_imp_t
#if defined(_CRT_WINDOWS) // for Windows-internal code
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 2 * sizeof(void*);
#elif defined(_WIN64) // ordinary 64-bit code
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72;
#else // vvv ordinary 32-bit code vvv
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 40;
#endif // ^^^ ordinary 32-bit code ^^^
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = alignof(void*);
using _Mtx_t = _Mtx_internal_imp_t*;
#ifdef _M_CEE // avoid warning LNK4248: unresolved typeref token for '_Cnd_internal_imp_t'; image may not run
using _Cnd_t = void*;
#else // ^^^ defined(_M_CEE) / !defined(_M_CEE) vvv
struct _Cnd_internal_imp_t;
struct _Cnd_internal_imp_t {
#if defined(_CRT_WINDOWS) // for Windows-internal code
static constexpr size_t _Cnd_internal_imp_size = 2 * sizeof(void*);
#elif defined(_WIN64) // ordinary 64-bit code
static constexpr size_t _Cnd_internal_imp_size = 72;
#else // vvv ordinary 32-bit code vvv
static constexpr size_t _Cnd_internal_imp_size = 40;
#endif // ^^^ ordinary 32-bit code ^^^
_STD _Aligned_storage_t<_Cnd_internal_imp_size, alignof(void*)> _Cv_storage;
};
using _Cnd_t = _Cnd_internal_imp_t*;
#endif // ^^^ !defined(_M_CEE) ^^^
} // extern "C"
#pragma pop_macro("new")

Просмотреть файл

@ -220,10 +220,10 @@ public:
private:
shared_ptr<mutex> _Myptr;
_Aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> _Cnd_storage;
_Cnd_internal_imp_t _Cnd_storage;
_NODISCARD _Cnd_t _Mycnd() noexcept { // get pointer to _Cnd_internal_imp_t inside _Cnd_storage
return reinterpret_cast<_Cnd_t>(&_Cnd_storage);
_NODISCARD _Cnd_t _Mycnd() noexcept {
return &_Cnd_storage;
}
template <class _Lock>

Просмотреть файл

@ -637,10 +637,10 @@ public:
}
private:
_Aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> _Cnd_storage;
_Cnd_internal_imp_t _Cnd_storage;
_Cnd_t _Mycnd() noexcept { // get pointer to _Cnd_internal_imp_t inside _Cnd_storage
return reinterpret_cast<_Cnd_t>(&_Cnd_storage);
_Cnd_t _Mycnd() noexcept {
return &_Cnd_storage;
}
};

Просмотреть файл

@ -14,7 +14,7 @@ extern "C" {
_CRTIMP2_PURE void __cdecl _Cnd_init_in_situ(const _Cnd_t cond) noexcept { // initialize condition variable in situ
new (cond->_get_cv()) Concurrency::details::stl_condition_variable_win7;
new (Concurrency::details::_Get_cond_var(cond)) Concurrency::details::stl_condition_variable_win7;
}
_CRTIMP2_PURE void __cdecl _Cnd_destroy_in_situ(_Cnd_t) noexcept {} // destroy condition variable in situ
@ -54,7 +54,7 @@ _CRTIMP2_PURE void __cdecl _Mtx_reset_owner(_Mtx_t mtx) noexcept { // set owner
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) noexcept { // wait until signaled
const auto cs = &mtx->_Critical_section;
_Mtx_clear_owner(mtx);
cond->_get_cv()->wait(cs);
Concurrency::details::_Get_cond_var(cond)->wait(cs);
_Mtx_reset_owner(mtx);
return _Thrd_result::_Success; // TRANSITION, ABI: Always succeeds
}
@ -66,13 +66,14 @@ _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_timedwait(
const auto cs = &mtx->_Critical_section;
if (target == nullptr) { // no target time specified, wait on mutex
_Mtx_clear_owner(mtx);
cond->_get_cv()->wait(cs);
Concurrency::details::_Get_cond_var(cond)->wait(cs);
_Mtx_reset_owner(mtx);
} else { // target time specified, wait for it
_timespec64 now;
_Timespec64_get_sys(&now);
_Mtx_clear_owner(mtx);
if (!cond->_get_cv()->wait_for(cs, _Xtime_diff_to_millis2(target, &now))) { // report timeout
if (!Concurrency::details::_Get_cond_var(cond)->wait_for(
cs, _Xtime_diff_to_millis2(target, &now))) { // report timeout
_Timespec64_get_sys(&now);
if (_Xtime_diff_to_millis2(target, &now) == 0) {
res = _Thrd_result::_Timedout;
@ -84,12 +85,12 @@ _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_timedwait(
}
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_signal(const _Cnd_t cond) noexcept { // release one waiting thread
cond->_get_cv()->notify_one();
Concurrency::details::_Get_cond_var(cond)->notify_one();
return _Thrd_result::_Success; // TRANSITION, ABI: Always succeeds
}
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_broadcast(const _Cnd_t cond) noexcept { // release all waiting threads
cond->_get_cv()->notify_all();
Concurrency::details::_Get_cond_var(cond)->notify_all();
return _Thrd_result::_Success; // TRANSITION, ABI: Always succeeds
}

Просмотреть файл

@ -3,6 +3,7 @@
#pragma once
#include <__msvc_threads_core.hpp>
#include <cstdlib>
#include <type_traits>
@ -43,18 +44,8 @@ namespace Concurrency {
CONDITION_VARIABLE m_condition_variable = CONDITION_VARIABLE_INIT;
};
[[nodiscard]] inline stl_condition_variable_win7* _Get_cond_var(::_Cnd_internal_imp_t* _Cond) noexcept {
return reinterpret_cast<stl_condition_variable_win7*>(&_Cond->_Cv_storage);
}
} // namespace details
} // namespace Concurrency
extern "C" {
struct _Cnd_internal_imp_t {
std::_Aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> cv;
[[nodiscard]] Concurrency::details::stl_condition_variable_win7* _get_cv() noexcept {
// get pointer to implementation
return reinterpret_cast<Concurrency::details::stl_condition_variable_win7*>(&cv);
}
};
} // extern "C"

Просмотреть файл

@ -50,7 +50,7 @@ _Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, c
mtx->_Thread_id = -1;
--mtx->_Count;
if (!cond->_get_cv()->wait_for(cs, target_ms)) { // report timeout
if (!Concurrency::details::_Get_cond_var(cond)->wait_for(cs, target_ms)) { // report timeout
const auto end_ms = GetTickCount64();
if (end_ms - start_ms >= target_ms) {
res = _Thrd_result::_Timedout;