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

<xthreads.h>: Use enum class _Thrd_result for type safety #3897

Merged
merged 2 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions stl/inc/condition_variable
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,10 @@ private:
const shared_ptr<mutex> _Ptr = _Myptr; // for immunity to *this destruction
unique_lock<mutex> _Guard{*_Ptr};
_Unlock_guard<_Lock> _Unlock_outer{_Lck};
const int _Res = _Cnd_timedwait(_Mycnd(), _Ptr->_Mymtx(), _Abs_time);
const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Ptr->_Mymtx(), _Abs_time);
_Guard.unlock();

if (_Res == _Thrd_success) {
if (_Res == _Thrd_result::_Thrd_success) {
return cv_status::no_timeout;
} else {
return cv_status::timeout;
Expand Down
8 changes: 4 additions & 4 deletions stl/inc/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public:
_Mutex_base& operator=(const _Mutex_base&) = delete;

void lock() {
if (_Mtx_lock(_Mymtx()) != _Thrd_success) {
if (_Mtx_lock(_Mymtx()) != _Thrd_result::_Thrd_success) {
// undefined behavior, only occurs for plain mutexes (N4950 [thread.mutex.requirements.mutex.general]/6)
_STD _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
}
Expand All @@ -69,7 +69,7 @@ public:

_NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept /* strengthened */ {
// false may be from undefined behavior for plain mutexes (N4950 [thread.mutex.requirements.mutex.general]/6)
return _Mtx_trylock(_Mymtx()) == _Thrd_success;
return _Mtx_trylock(_Mymtx()) == _Thrd_result::_Thrd_success;
}

void unlock() noexcept /* strengthened */ {
Expand Down Expand Up @@ -719,9 +719,9 @@ private:
}

// Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow
const int _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);
const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), _Abs_time);

if (_Res == _Thrd_success) {
if (_Res == _Thrd_result::_Thrd_success) {
return cv_status::no_timeout;
} else {
return cv_status::timeout;
Expand Down
4 changes: 2 additions & 2 deletions stl/inc/thread
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public:
_Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
}

if (_Thrd_join(_Thr, nullptr) != _Thrd_success) {
if (_Thrd_join(_Thr, nullptr) != _Thrd_result::_Thrd_success) {
_Throw_Cpp_error(_NO_SUCH_PROCESS);
}

Expand All @@ -137,7 +137,7 @@ public:
_Throw_Cpp_error(_INVALID_ARGUMENT);
}

if (_Thrd_detach(_Thr) != _Thrd_success) {
if (_Thrd_detach(_Thr) != _Thrd_result::_Thrd_success) {
_Throw_Cpp_error(_INVALID_ARGUMENT);
}

Expand Down
26 changes: 13 additions & 13 deletions stl/inc/xthreads.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ struct _Cnd_internal_imp_t;
using _Cnd_t = _Cnd_internal_imp_t*;
#endif // ^^^ !defined(_M_CEE) ^^^

enum { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
enum class _Thrd_result : int { _Thrd_success, _Thrd_nomem, _Thrd_timedout, _Thrd_busy, _Thrd_error };
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

// threads
_CRTIMP2_PURE int __cdecl _Thrd_detach(_Thrd_t);
_CRTIMP2_PURE int __cdecl _Thrd_join(_Thrd_t, int*);
_CRTIMP2_PURE _Thrd_result __cdecl _Thrd_detach(_Thrd_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Thrd_join(_Thrd_t, int*);
_CRTIMP2_PURE void __cdecl _Thrd_sleep(const _timespec64*);
_CRTIMP2_PURE void __cdecl _Thrd_yield();
_CRTIMP2_PURE unsigned int __cdecl _Thrd_hardware_concurrency();
Expand All @@ -105,15 +105,15 @@ enum { // mutex types
_Mtx_recursive = 0x100
};

_CRTIMP2_PURE int __cdecl _Mtx_init(_Mtx_t*, int);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_init(_Mtx_t*, int);
_CRTIMP2_PURE void __cdecl _Mtx_destroy(_Mtx_t);
_CRTIMP2_PURE void __cdecl _Mtx_init_in_situ(_Mtx_t, int);
_CRTIMP2_PURE void __cdecl _Mtx_destroy_in_situ(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_current_owns(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_lock(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_trylock(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_timedlock(_Mtx_t, const _timespec64*);
_CRTIMP2_PURE int __cdecl _Mtx_unlock(_Mtx_t); // TRANSITION, ABI: always returns _Thrd_success
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_lock(_Mtx_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_trylock(_Mtx_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_timedlock(_Mtx_t, const _timespec64*);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_unlock(_Mtx_t); // TRANSITION, ABI: Always succeeds

_CRTIMP2_PURE void* __cdecl _Mtx_getconcrtcs(_Mtx_t);
_CRTIMP2_PURE void __cdecl _Mtx_clear_owner(_Mtx_t);
Expand All @@ -129,14 +129,14 @@ void __cdecl _Smtx_unlock_exclusive(_Smtx_t*);
void __cdecl _Smtx_unlock_shared(_Smtx_t*);

// condition variables
_CRTIMP2_PURE int __cdecl _Cnd_init(_Cnd_t*);
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_init(_Cnd_t*);
_CRTIMP2_PURE void __cdecl _Cnd_destroy(_Cnd_t);
_CRTIMP2_PURE void __cdecl _Cnd_init_in_situ(_Cnd_t);
_CRTIMP2_PURE void __cdecl _Cnd_destroy_in_situ(_Cnd_t);
_CRTIMP2_PURE int __cdecl _Cnd_wait(_Cnd_t, _Mtx_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE int __cdecl _Cnd_timedwait(_Cnd_t, _Mtx_t, const _timespec64*);
_CRTIMP2_PURE int __cdecl _Cnd_broadcast(_Cnd_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE int __cdecl _Cnd_signal(_Cnd_t); // TRANSITION, ABI: Always returns _Thrd_success
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_wait(_Cnd_t, _Mtx_t); // TRANSITION, ABI: Always succeeds
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_timedwait(_Cnd_t, _Mtx_t, const _timespec64*);
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_broadcast(_Cnd_t); // TRANSITION, ABI: Always succeeds
_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_signal(_Cnd_t); // TRANSITION, ABI: Always succeeds
_CRTIMP2_PURE void __cdecl _Cnd_register_at_thread_exit(_Cnd_t, _Mtx_t, int*);
_CRTIMP2_PURE void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_t);
_CRTIMP2_PURE void __cdecl _Cnd_do_broadcast_at_thread_exit();
Expand Down
26 changes: 13 additions & 13 deletions stl/src/cond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ void _Cnd_init_in_situ(const _Cnd_t cond) { // initialize condition variable in

void _Cnd_destroy_in_situ(_Cnd_t) {} // destroy condition variable in situ

int _Cnd_init(_Cnd_t* const pcond) { // initialize
_Thrd_result _Cnd_init(_Cnd_t* const pcond) { // initialize
*pcond = nullptr;

const auto cond = static_cast<_Cnd_t>(_calloc_crt(1, sizeof(_Cnd_internal_imp_t)));
if (cond == nullptr) {
return _Thrd_nomem; // report alloc failed
return _Thrd_result::_Thrd_nomem; // report alloc failed
}

_Cnd_init_in_situ(cond);
*pcond = cond;
return _Thrd_success;
return _Thrd_result::_Thrd_success;
}

void _Cnd_destroy(const _Cnd_t cond) { // clean up
Expand All @@ -50,18 +50,18 @@ void _Cnd_destroy(const _Cnd_t cond) { // clean up
}
}

int _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled
_Thrd_result _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx) { // wait until signaled
const auto cs = &mtx->_Critical_section;
_Mtx_clear_owner(mtx);
cond->_get_cv()->wait(cs);
_Mtx_reset_owner(mtx);
return _Thrd_success; // TRANSITION, ABI: Always returns _Thrd_success
return _Thrd_result::_Thrd_success; // TRANSITION, ABI: Always succeeds
}

// wait until signaled or timeout
int _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const target) {
int res = _Thrd_success;
const auto cs = &mtx->_Critical_section;
_Thrd_result _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const target) {
_Thrd_result res = _Thrd_result::_Thrd_success;
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);
Expand All @@ -73,22 +73,22 @@ int _Cnd_timedwait(const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const
if (!cond->_get_cv()->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_timedout;
res = _Thrd_result::_Thrd_timedout;
}
}
_Mtx_reset_owner(mtx);
}
return res;
}

int _Cnd_signal(const _Cnd_t cond) { // release one waiting thread
_Thrd_result _Cnd_signal(const _Cnd_t cond) { // release one waiting thread
cond->_get_cv()->notify_one();
return _Thrd_success; // TRANSITION, ABI: Always returns _Thrd_success
return _Thrd_result::_Thrd_success; // TRANSITION, ABI: Always succeeds
}

int _Cnd_broadcast(const _Cnd_t cond) { // release all waiting threads
_Thrd_result _Cnd_broadcast(const _Cnd_t cond) { // release all waiting threads
cond->_get_cv()->notify_all();
return _Thrd_success; // TRANSITION, ABI: Always returns _Thrd_success
return _Thrd_result::_Thrd_success; // TRANSITION, ABI: Always succeeds
}

/*
Expand Down
22 changes: 11 additions & 11 deletions stl/src/cthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,29 @@ _EXTERN_C
}

// TRANSITION, ABI: _Thrd_start() is preserved for binary compatibility
_CRTIMP2_PURE int _Thrd_start(_Thrd_t* thr, _Thrd_callback_t func, void* b) { // start a thread
_CRTIMP2_PURE _Thrd_result _Thrd_start(_Thrd_t* thr, _Thrd_callback_t func, void* b) { // start a thread
thr->_Hnd = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, func, b, 0, &thr->_Id));
return thr->_Hnd == nullptr ? _Thrd_error : _Thrd_success;
return thr->_Hnd == nullptr ? _Thrd_result::_Thrd_error : _Thrd_result::_Thrd_success;
}

int _Thrd_join(_Thrd_t thr, int* code) { // returns when thread terminates
_Thrd_result _Thrd_join(_Thrd_t thr, int* code) { // returns when thread terminates
if (WaitForSingleObjectEx(thr._Hnd, INFINITE, FALSE) == WAIT_FAILED) {
return _Thrd_error;
return _Thrd_result::_Thrd_error;
}

if (code) { // TRANSITION, ABI: code is preserved for binary compatibility
unsigned long res;
if (!GetExitCodeThread(thr._Hnd, &res)) {
return _Thrd_error;
return _Thrd_result::_Thrd_error;
}
*code = static_cast<int>(res);
}

return CloseHandle(thr._Hnd) ? _Thrd_success : _Thrd_error;
return CloseHandle(thr._Hnd) ? _Thrd_result::_Thrd_success : _Thrd_result::_Thrd_error;
}

int _Thrd_detach(_Thrd_t thr) { // tell OS to release thread's resources when it terminates
return CloseHandle(thr._Hnd) ? _Thrd_success : _Thrd_error;
_Thrd_result _Thrd_detach(_Thrd_t thr) { // tell OS to release thread's resources when it terminates
return CloseHandle(thr._Hnd) ? _Thrd_result::_Thrd_success : _Thrd_result::_Thrd_error;
}

void _Thrd_sleep(const _timespec64* xt) { // suspend thread until time xt
Expand Down Expand Up @@ -109,8 +109,8 @@ unsigned int _Thrd_hardware_concurrency() { // return number of processors
}

// TRANSITION, ABI: _Thrd_create() is preserved for binary compatibility
_CRTIMP2_PURE int _Thrd_create(_Thrd_t* thr, _Thrd_start_t func, void* d) { // create thread
int res;
_CRTIMP2_PURE _Thrd_result _Thrd_create(_Thrd_t* thr, _Thrd_start_t func, void* d) { // create thread
_Thrd_result res;
_Thrd_binder b;
int started = 0;
_Cnd_t cond;
Expand All @@ -123,7 +123,7 @@ _CRTIMP2_PURE int _Thrd_create(_Thrd_t* thr, _Thrd_start_t func, void* d) { // c
b.mtx = &mtx;
b.started = &started;
_Mtx_lock(mtx);
if ((res = _Thrd_start(thr, _Thrd_runner, &b)) == _Thrd_success) { // wait for handshake
if ((res = _Thrd_start(thr, _Thrd_runner, &b)) == _Thrd_result::_Thrd_success) { // wait for handshake
while (!started) {
_Cnd_wait(cond, mtx);
}
Expand Down
32 changes: 16 additions & 16 deletions stl/src/mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ void _Mtx_destroy_in_situ(_Mtx_t mtx) { // destroy mutex in situ
(void) mtx;
}

int _Mtx_init(_Mtx_t* mtx, int type) { // initialize mutex
_Thrd_result _Mtx_init(_Mtx_t* mtx, int type) { // initialize mutex
*mtx = nullptr;

_Mtx_t mutex = static_cast<_Mtx_t>(_calloc_crt(1, sizeof(_Mtx_internal_imp_t)));

if (mutex == nullptr) {
return _Thrd_nomem; // report alloc failed
return _Thrd_result::_Thrd_nomem; // report alloc failed
}

_Mtx_init_in_situ(mutex, type);

*mtx = mutex;
return _Thrd_success;
return _Thrd_result::_Thrd_success;
}

void _Mtx_destroy(_Mtx_t mtx) { // destroy mutex
Expand All @@ -76,15 +76,15 @@ void _Mtx_destroy(_Mtx_t mtx) { // destroy mutex
}
}

static int mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock mutex
static _Thrd_result mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock mutex
if ((mtx->_Type & ~_Mtx_recursive) == _Mtx_plain) { // set the lock
if (mtx->_Thread_id != static_cast<long>(GetCurrentThreadId())) { // not current thread, do lock
AcquireSRWLockExclusive(get_srw_lock(mtx));
mtx->_Thread_id = static_cast<long>(GetCurrentThreadId());
}
++mtx->_Count;

return _Thrd_success;
return _Thrd_result::_Thrd_success;
} else { // handle timed or recursive mutex
int res = WAIT_TIMEOUT;
if (target == nullptr) { // no target --> plain wait (i.e. infinite timeout)
Expand Down Expand Up @@ -137,22 +137,22 @@ static int mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock mutex
switch (res) {
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
return _Thrd_success;
return _Thrd_result::_Thrd_success;

case WAIT_TIMEOUT:
if (target == nullptr || (target->tv_sec == 0 && target->tv_nsec == 0)) {
return _Thrd_busy;
return _Thrd_result::_Thrd_busy;
} else {
return _Thrd_timedout;
return _Thrd_result::_Thrd_timedout;
}

default:
return _Thrd_error;
return _Thrd_result::_Thrd_error;
}
}
}

int _Mtx_unlock(_Mtx_t mtx) { // unlock mutex
_Thrd_result _Mtx_unlock(_Mtx_t mtx) { // unlock mutex
_THREAD_ASSERT(
1 <= mtx->_Count && mtx->_Thread_id == static_cast<long>(GetCurrentThreadId()), "unlock of unowned mutex");

Expand All @@ -163,27 +163,27 @@ int _Mtx_unlock(_Mtx_t mtx) { // unlock mutex
_Analysis_assume_lock_held_(*srw_lock);
ReleaseSRWLockExclusive(srw_lock);
}
return _Thrd_success; // TRANSITION, ABI: always returns _Thrd_success
return _Thrd_result::_Thrd_success; // TRANSITION, ABI: Always succeeds
}

int _Mtx_lock(_Mtx_t mtx) { // lock mutex
_Thrd_result _Mtx_lock(_Mtx_t mtx) { // lock mutex
return mtx_do_lock(mtx, nullptr);
}

int _Mtx_trylock(_Mtx_t mtx) { // attempt to lock try_mutex
_Thrd_result _Mtx_trylock(_Mtx_t mtx) { // attempt to lock try_mutex
_timespec64 xt;
_THREAD_ASSERT((mtx->_Type & (_Mtx_try | _Mtx_timed)) != 0, "trylock not supported by mutex");
xt.tv_sec = 0;
xt.tv_nsec = 0;
return mtx_do_lock(mtx, &xt);
}

int _Mtx_timedlock(_Mtx_t mtx, const _timespec64* xt) { // attempt to lock timed mutex
int res;
_Thrd_result _Mtx_timedlock(_Mtx_t mtx, const _timespec64* xt) { // attempt to lock timed mutex
_Thrd_result res;

_THREAD_ASSERT((mtx->_Type & _Mtx_timed) != 0, "timedlock not supported by mutex");
res = mtx_do_lock(mtx, xt);
return res == _Thrd_busy ? _Thrd_timedout : res;
return res == _Thrd_result::_Thrd_busy ? _Thrd_result::_Thrd_timedout : res;
}

int _Mtx_current_owns(_Mtx_t mtx) { // test if current thread owns mutex
Expand Down
10 changes: 5 additions & 5 deletions stl/src/thread0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ static constexpr errc codes[] = {

// TRANSITION, ABI: preserved for binary compatibility
[[noreturn]] _CRTIMP2_PURE void __cdecl _Throw_C_error(int code) { // throw error object for C error
switch (code) { // select the exception
case _Thrd_nomem:
case _Thrd_timedout:
switch (static_cast<_Thrd_result>(code)) { // select the exception
case _Thrd_result::_Thrd_nomem:
case _Thrd_result::_Thrd_timedout:
_Throw_Cpp_error(_RESOURCE_UNAVAILABLE_TRY_AGAIN);

case _Thrd_busy:
case _Thrd_result::_Thrd_busy:
_Throw_Cpp_error(_DEVICE_OR_RESOURCE_BUSY);

case _Thrd_error:
case _Thrd_result::_Thrd_error:
_Throw_Cpp_error(_INVALID_ARGUMENT);

default:
Expand Down