Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 9 commits into from
Apr 9, 2024
Merged
40 changes: 14 additions & 26 deletions stl/inc/__msvc_threads_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
using _Mtx_t = _Mtx_internal_imp_t*;

struct _Cnd_internal_imp_t {
#if defined(_CRT_WINDOWS) // for Windows-internal code
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 2 * sizeof(void*);
static 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;
static 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;
static 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*;
_STD _Aligned_storage_t<_Cnd_internal_imp_size, alignof(void*)> _Cv_storage;
};

#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;
using _Cnd_t = _Cnd_internal_imp_t*;
#endif // ^^^ !defined(_M_CEE) ^^^
} // extern "C"

#pragma pop_macro("new")
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/condition_variable
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};

Expand Down
13 changes: 7 additions & 6 deletions stl/src/cond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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;
Expand All @@ -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
}

Expand Down
17 changes: 4 additions & 13 deletions stl/src/primitives.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#pragma once

#include <__msvc_threads_core.hpp>
#include <cstdlib>
#include <type_traits>

Expand Down Expand Up @@ -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 {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
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"
2 changes: 1 addition & 1 deletion stl/src/sharedmutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down