mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
sync: make Semaphore.*wait()
robust against interrupts by signals (#10491)
This commit is contained in:
@ -125,18 +125,69 @@ pub fn (mut sem Semaphore) post() {
|
||||
}
|
||||
|
||||
pub fn (mut sem Semaphore) wait() {
|
||||
C.sem_wait(&sem.sem)
|
||||
for {
|
||||
if C.sem_wait(&sem.sem) == 0 {
|
||||
return
|
||||
}
|
||||
e := C.errno
|
||||
match e {
|
||||
C.EINTR {
|
||||
continue // interrupted by signal
|
||||
}
|
||||
else {
|
||||
panic(unsafe { tos_clone(&byte(C.strerror(C.errno))) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `try_wait()` should return as fast as possible so error handling is only
|
||||
// done when debugging
|
||||
pub fn (mut sem Semaphore) try_wait() bool {
|
||||
return C.sem_trywait(&sem.sem) == 0
|
||||
$if !debug {
|
||||
return C.sem_trywait(&sem.sem) == 0
|
||||
} $else {
|
||||
if C.sem_trywait(&sem.sem) != 0 {
|
||||
e := C.errno
|
||||
match e {
|
||||
C.EAGAIN {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
panic(unsafe { tos_clone(&byte(C.strerror(C.errno))) })
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
||||
t_spec := timeout.timespec()
|
||||
return C.sem_timedwait(&sem.sem, &t_spec) == 0
|
||||
for {
|
||||
if C.sem_timedwait(&sem.sem, &t_spec) == 0 {
|
||||
return true
|
||||
}
|
||||
e := C.errno
|
||||
match e {
|
||||
C.EINTR {
|
||||
continue // interrupted by signal
|
||||
}
|
||||
C.ETIMEDOUT {
|
||||
break
|
||||
}
|
||||
else {
|
||||
panic(unsafe { tos_clone(&byte(C.strerror(e))) })
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn (sem Semaphore) destroy() bool {
|
||||
return C.sem_destroy(&sem.sem) == 0
|
||||
pub fn (sem Semaphore) destroy() {
|
||||
res := C.sem_destroy(&sem.sem)
|
||||
if res == 0 {
|
||||
return
|
||||
}
|
||||
panic(unsafe { tos_clone(&byte(C.strerror(res))) })
|
||||
}
|
||||
|
@ -220,6 +220,13 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
||||
return res == 0
|
||||
}
|
||||
|
||||
pub fn (mut sem Semaphore) destroy() bool {
|
||||
return C.pthread_cond_destroy(&sem.cond) == 0 && C.pthread_mutex_destroy(&sem.mtx) == 0
|
||||
pub fn (mut sem Semaphore) destroy() {
|
||||
mut res := C.pthread_cond_destroy(&sem.cond)
|
||||
if res == 0 {
|
||||
res = C.pthread_mutex_destroy(&sem.mtx)
|
||||
if res == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic(unsafe { tos_clone(&byte(C.strerror(res))) })
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ module sync
|
||||
import time
|
||||
|
||||
#include <synchapi.h>
|
||||
#include <time.h>
|
||||
|
||||
fn C.GetSystemTimeAsFileTime(lpSystemTimeAsFileTime &C._FILETIME)
|
||||
fn C.InitializeConditionVariable(voidptr)
|
||||
fn C.WakeConditionVariable(voidptr)
|
||||
fn C.SleepConditionVariableSRW(voidptr, voidptr, u32, u32) int
|
||||
@ -170,8 +172,12 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
mut ft_start := C._FILETIME{}
|
||||
C.GetSystemTimeAsFileTime(&ft_start)
|
||||
time_end := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) +
|
||||
u64(timeout / (100 * time.nanosecond))
|
||||
mut t_ms := u32(timeout / time.millisecond)
|
||||
C.AcquireSRWLockExclusive(&sem.mtx)
|
||||
t_ms := u32(timeout / time.millisecond)
|
||||
mut res := 0
|
||||
c = C.atomic_load_u32(&sem.count)
|
||||
|
||||
@ -191,11 +197,16 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
||||
break outer
|
||||
}
|
||||
}
|
||||
C.GetSystemTimeAsFileTime(&ft_start)
|
||||
time_now := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) // in 100ns
|
||||
if time_now > time_end {
|
||||
break outer // timeout exceeded
|
||||
}
|
||||
t_ms = u32((time_end - time_now) / 10000)
|
||||
}
|
||||
C.ReleaseSRWLockExclusive(&sem.mtx)
|
||||
return res != 0
|
||||
}
|
||||
|
||||
pub fn (s Semaphore) destroy() bool {
|
||||
return true
|
||||
pub fn (s Semaphore) destroy() {
|
||||
}
|
||||
|
Reference in New Issue
Block a user