Changeset View
Changeset View
Standalone View
Standalone View
source/lib/sysdep/os/win/wposix/wpthread.cpp
/* Copyright (C) 2010 Wildfire Games. | /* Copyright (C) 2020 Wildfire Games. | ||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* "Software"), to deal in the Software without restriction, including | * "Software"), to deal in the Software without restriction, including | ||||
* without limitation the rights to use, copy, modify, merge, publish, | * without limitation the rights to use, copy, modify, merge, publish, | ||||
* distribute, sublicense, and/or sell copies of the Software, and to | * distribute, sublicense, and/or sell copies of the Software, and to | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
▲ Show 20 Lines • Show All 459 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
HANDLE h = HANDLE_from_sem_t(sem); | HANDLE h = HANDLE_from_sem_t(sem); | ||||
DWORD ret = WaitForSingleObject(h, INFINITE); | DWORD ret = WaitForSingleObject(h, INFINITE); | ||||
ENSURE(ret == WAIT_OBJECT_0); | ENSURE(ret == WAIT_OBJECT_0); | ||||
return 0; | return 0; | ||||
} | } | ||||
// helper function for sem_timedwait - multiple return is convenient. | |||||
// converts an absolute timeout deadline into a relative length for use with | |||||
// WaitForSingleObject with the following peculiarity: if the semaphore | |||||
// could be locked immediately, abs_timeout must be ignored (see SUS). | |||||
// to that end, we return a timeout of 0 and pass back <valid> = false if | |||||
// abs_timeout is invalid. | |||||
static DWORD calc_timeout_length_ms(const struct timespec* abs_timeout, | |||||
bool& timeout_is_valid) | |||||
{ | |||||
timeout_is_valid = false; | |||||
if(!abs_timeout) | |||||
return 0; | |||||
// SUS requires we fail if not normalized | |||||
if(abs_timeout->tv_nsec >= 1000000000) | |||||
return 0; | |||||
struct timespec cur_time; | |||||
if(clock_gettime(CLOCK_REALTIME, &cur_time) != 0) | |||||
return 0; | |||||
timeout_is_valid = true; | |||||
// convert absolute deadline to relative length, rounding up to [ms]. | |||||
// note: use i64 to avoid overflow in multiply. | |||||
const i64 ds = abs_timeout->tv_sec - cur_time.tv_sec; | |||||
const long dn = abs_timeout->tv_nsec - cur_time.tv_nsec; | |||||
i64 length_ms = ds*1000 + (dn+500000)/1000000; | |||||
// .. deadline already reached; we'll still attempt to lock once | |||||
if(length_ms < 0) | |||||
return 0; | |||||
// .. length > 49 days => result won't fit in 32 bits. most likely bogus. | |||||
// note: we're careful to avoid returning exactly -1 since | |||||
// that's the Win32 INFINITE value. | |||||
if(length_ms >= 0xFFFFFFFF) | |||||
{ | |||||
WARN_IF_ERR(ERR::LIMIT); | |||||
length_ms = 0xfffffffe; | |||||
} | |||||
return (DWORD)(length_ms & 0xFFFFFFFF); | |||||
} | |||||
int sem_timedwait(sem_t* sem, const struct timespec* abs_timeout) | |||||
vladislavbelov: There are usages (commented or not) of the `sem_timedwait` in our code. | |||||
Done Inline ActionsNot on windows. And if on Linux, then it uses native functions not this weird emulation. I think this whole file will be removed when @wraitii finish his migration to std::thread. I can delete wprofiler.h if you want as it's not used. Stan: Not on windows. And if on Linux, then it uses native functions not this weird emulation. I… | |||||
Not Done Inline ActionsMaybe, but at least you have to remove usages of the removed functions. vladislavbelov: Maybe, but at least you have to remove usages of the removed functions. | |||||
{ | |||||
bool timeout_is_valid; | |||||
DWORD timeout_ms = calc_timeout_length_ms(abs_timeout, timeout_is_valid); | |||||
HANDLE h = HANDLE_from_sem_t(sem); | |||||
DWORD ret = WaitForSingleObject(h, timeout_ms); | |||||
// successfully decremented semaphore; bail. | |||||
if(ret == WAIT_OBJECT_0) | |||||
return 0; | |||||
// we're going to return -1. decide what happened: | |||||
// .. abs_timeout was invalid (must not check this before trying to lock) | |||||
if(!timeout_is_valid) | |||||
errno = EINVAL; | |||||
// .. timeout reached (not a failure) | |||||
else if(ret == WAIT_TIMEOUT) | |||||
errno = ETIMEDOUT; | |||||
return -1; | |||||
} | |||||
// wait until semaphore is locked or a message arrives. non-portable. | // wait until semaphore is locked or a message arrives. non-portable. | ||||
// | // | ||||
// background: on Win32, UI threads must periodically pump messages, or | // background: on Win32, UI threads must periodically pump messages, or | ||||
// else deadlock may result (see WaitForSingleObject docs). that entails | // else deadlock may result (see WaitForSingleObject docs). that entails | ||||
// avoiding any blocking functions. when event waiting is needed, | // avoiding any blocking functions. when event waiting is needed, | ||||
// one cheap workaround would be to time out periodically and pump messages. | // one cheap workaround would be to time out periodically and pump messages. | ||||
// that would work, but either wastes CPU time waiting, or introduces | // that would work, but either wastes CPU time waiting, or introduces | ||||
// message latency. to avoid this, we provide an API similar to sem_wait and | // message latency. to avoid this, we provide an API similar to sem_wait and | ||||
▲ Show 20 Lines • Show All 156 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
There are usages (commented or not) of the sem_timedwait in our code.