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

constexpr mutex #2309

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,19 @@ class condition_variable_any;

class _Mutex_base { // base class for all mutex types
public:
_Mutex_base(int _Flags = 0) noexcept {
#ifdef __CUDACC__ // TRANSITION, CUDA
_Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) {
_Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try);
}
#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv
constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) {
if (!__builtin_is_constant_evaluated()) {
// If mutex is created in runtime, it may outlive the module it is allocated in;
// Use usual in-place construction.
_Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try);
}
}
#endif // ^^^ not CUDA ^^^

~_Mutex_base() noexcept {
_Mtx_destroy_in_situ(_Mymtx());
Expand Down Expand Up @@ -76,7 +86,7 @@ private:
friend condition_variable;
friend condition_variable_any;

aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage;
_Mtx_internal_imp_2_t _Mtx_storage;

_Mtx_t _Mymtx() noexcept { // get pointer to _Mtx_internal_imp_t inside _Mtx_storage
return reinterpret_cast<_Mtx_t>(&_Mtx_storage);
Expand All @@ -85,8 +95,11 @@ private:

class mutex : public _Mutex_base { // class for mutual exclusion
public:
/* constexpr */ mutex() noexcept // TRANSITION, ABI
: _Mutex_base() {}
#ifdef __CUDACC__ // TRANSITION, CUDA
mutex() noexcept : _Mutex_base() {}
#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv
constexpr mutex() noexcept : _Mutex_base() {}
#endif // ^^^ not CUDA ^^^
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved

mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
Expand Down
77 changes: 73 additions & 4 deletions stl/inc/xthreads.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ _INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 4;
#endif // _WIN64
#else // _CRT_WINDOWS
#ifdef _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72;
_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8;
#else // _WIN64
_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 48;
_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 4;
Expand Down Expand Up @@ -134,6 +134,75 @@ inline int _Check_C_return(int _Res) { // throw exception on failure
return _Res;
}
_STD_END

#ifdef _WIN64
_INLINE_VAR constexpr size_t _Stl_critical_section_size = 64;
_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 8;
#else // ^^^ 64-bit OS ^^^ / vvv 32-bit OS vvv
_INLINE_VAR constexpr size_t _Stl_critical_section_size = 36;
_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4;
#endif // ^^^32 - bit OS ^^^

// Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr
struct _Mtx_internal_imp_2_t {
struct alignas(_Stl_critical_section_alignment) _Data_win7_t {
static void __fastcall _Lock_impl(_Data_win7_t* _Data) {
_Smtx_lock_exclusive(&_Data->_Mtx);
}

static bool __fastcall _Try_lock_impl(_Data_win7_t* _Data) {
return _Smtx_try_lock_exclusive(&_Data->_Mtx) != 0;
}

#ifdef _M_IX86
static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int, unsigned int) {
// STL will call try_lock_for once again if this call will not succeed
return _Data_win7_t::_Try_lock_impl(_Data);
}
#else // ^^^ x86 ^^^ / vvv not x86 vvv
static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int) {
// STL will call try_lock_for once again if this call will not succeed
return _Data_win7_t::_Try_lock_impl(_Data);
}
#endif // ^^^ not x86
static void __fastcall _Unlock_impl(_Data_win7_t* _Data) {
_Smtx_unlock_exclusive(&_Data->_Mtx);
}

static void __fastcall _Destroy_impl(_Data_win7_t*) {}

struct _VTable {
void(__fastcall* _Lock)(_Data_win7_t*);
bool(__fastcall* _Try_lock)(_Data_win7_t*);
#ifdef _M_IX86
bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int);
#else // ^^^ x86 ^^^ / vvv not x86 vvv
bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int);
#endif // ^^^ not x86
void(__fastcall* _Unlock)(_Data_win7_t*);
void(__fastcall* _Destroy)(_Data_win7_t*);
};

static constexpr _VTable _Vtbl{_Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl, _Destroy_impl};

const _VTable* _VPtr = &_Vtbl;
_Smtx_t _Mtx = {};
};

int _Type;
union alignas(_Stl_critical_section_alignment) _Data_t {
char _Data[_Stl_critical_section_size];
_Data_win7_t _Data_win7;

constexpr _Data_t() : _Data_win7() {}
~_Data_t() {}
} _Cs;
long _Thread_id = -1;
int _Count = 0;

constexpr _Mtx_internal_imp_2_t(int _Type_) : _Type(_Type_) {}
};

#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
Expand Down
5 changes: 5 additions & 0 deletions stl/src/mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ struct _Mtx_internal_imp_t { // ConcRT mutex
return reinterpret_cast<Concurrency::details::stl_critical_section_interface*>(&cs);
}
};
static_assert(Concurrency::details::stl_critical_section_max_size == _Stl_critical_section_size,
"Incorrect stl_critical_section_max_size");

static_assert(Concurrency::details::stl_critical_section_max_alignment == _Stl_critical_section_alignment,
"Incorrect stl_critical_section_max_alignment");

static_assert(sizeof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_size, "incorrect _Mtx_internal_imp_size");
static_assert(alignof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_alignment, "incorrect _Mtx_internal_imp_alignment");
Expand Down
36 changes: 1 addition & 35 deletions stl/src/primitives.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ namespace Concurrency {
}

bool try_lock() override {
return __crtTryAcquireSRWLockExclusive(&m_srw_lock) != 0;
return TryAcquireSRWLockExclusive(&m_srw_lock) != 0;
}

bool try_lock_for(unsigned int) override {
Expand Down Expand Up @@ -193,45 +193,11 @@ namespace Concurrency {
}

inline void create_stl_critical_section(stl_critical_section_interface* p) {
#ifdef _CRT_WINDOWS
new (p) stl_critical_section_win7;
#else
switch (__stl_sync_api_impl_mode) {
case __stl_sync_api_modes_enum::normal:
case __stl_sync_api_modes_enum::win7:
if (are_win7_sync_apis_available()) {
new (p) stl_critical_section_win7;
return;
}
// fall through
case __stl_sync_api_modes_enum::vista:
new (p) stl_critical_section_vista;
return;
default:
abort();
}
#endif // _CRT_WINDOWS
}

inline void create_stl_condition_variable(stl_condition_variable_interface* p) {
#ifdef _CRT_WINDOWS
new (p) stl_condition_variable_win7;
#else
switch (__stl_sync_api_impl_mode) {
case __stl_sync_api_modes_enum::normal:
case __stl_sync_api_modes_enum::win7:
if (are_win7_sync_apis_available()) {
new (p) stl_condition_variable_win7;
return;
}
// fall through
case __stl_sync_api_modes_enum::vista:
new (p) stl_condition_variable_vista;
return;
default:
abort();
}
#endif // _CRT_WINDOWS
}

#if defined _CRT_WINDOWS
Expand Down
4 changes: 1 addition & 3 deletions stl/src/winapisupp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,7 @@ extern "C" BOOL __cdecl __crtQueueUserWorkItem(_In_ LPTHREAD_START_ROUTINE, _In_
#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7

extern "C" BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK const pLock) {
DYNAMICGETCACHEDFUNCTION(PFNTRYACQUIRESRWLOCKEXCLUSIVE, TryAcquireSRWLockExclusive, pfTryAcquireSRWLockExclusive);
return pfTryAcquireSRWLockExclusive(pLock);
// Don't have fallbacks because the only caller (in primitives.hpp) will check the existence before calling
return TryAcquireSRWLockExclusive(pLock);
}

#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN7
Expand Down