1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

sync: add Mutex.destroy and RwMutex.destroy methods (#18351)

This commit is contained in:
kbkpbot 2023-06-06 19:45:12 +08:00 committed by GitHub
parent c1e302a38d
commit 632c466aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 4 deletions

View File

@ -21,10 +21,12 @@ fn C.pthread_mutex_destroy(voidptr) int
fn C.pthread_rwlockattr_init(voidptr) int
fn C.pthread_rwlockattr_setkind_np(voidptr, int) int
fn C.pthread_rwlockattr_setpshared(voidptr, int) int
fn C.pthread_rwlockattr_destroy(voidptr) int
fn C.pthread_rwlock_init(voidptr, voidptr) int
fn C.pthread_rwlock_rdlock(voidptr) int
fn C.pthread_rwlock_wrlock(voidptr) int
fn C.pthread_rwlock_unlock(voidptr) int
fn C.pthread_rwlock_destroy(voidptr) int
fn C.sem_init(voidptr, int, u32) int
fn C.sem_post(voidptr) int
fn C.sem_wait(voidptr) int
@ -64,22 +66,26 @@ pub struct Semaphore {
sem C.sem_t
}
// new_mutex create and init a new mutex object. You should not call `init` again.
pub fn new_mutex() &Mutex {
mut m := &Mutex{}
m.init()
return m
}
// init the mutex object.
pub fn (mut m Mutex) init() {
C.pthread_mutex_init(&m.mutex, C.NULL)
}
// new_rwmutex create and init a new rwmutex object. You should not call `init` again.
pub fn new_rwmutex() &RwMutex {
mut m := &RwMutex{}
m.init()
return m
}
// init the rwmutex object.
pub fn (mut m RwMutex) init() {
a := RwMutexAttr{}
C.pthread_rwlockattr_init(&a.attr)
@ -87,55 +93,82 @@ pub fn (mut m RwMutex) init() {
C.pthread_rwlockattr_setkind_np(&a.attr, C.PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
C.pthread_rwlockattr_setpshared(&a.attr, C.PTHREAD_PROCESS_PRIVATE)
C.pthread_rwlock_init(&m.mutex, &a.attr)
C.pthread_rwlockattr_destroy(&a.attr) // destroy the attr when done
}
// @lock(), for *manual* mutex handling, since `lock` is a keyword
// @lock the mutex, wait and return after got the mutex lock.
pub fn (mut m Mutex) @lock() {
C.pthread_mutex_lock(&m.mutex)
}
// unlock the mutex. The mutex is released.
pub fn (mut m Mutex) unlock() {
C.pthread_mutex_unlock(&m.mutex)
}
// RwMutex has separate read- and write locks
// destroy the mutex object.
pub fn (mut m Mutex) destroy() {
res := C.pthread_mutex_destroy(&m.mutex)
if res == 0 {
return
}
panic(unsafe { tos_clone(&u8(C.strerror(res))) })
}
// @rlock read-lock the rwmutex, wait and return after got read access.
pub fn (mut m RwMutex) @rlock() {
C.pthread_rwlock_rdlock(&m.mutex)
}
// @lock read & write-lock the rwmutex, wait and return after got read & write access.
pub fn (mut m RwMutex) @lock() {
C.pthread_rwlock_wrlock(&m.mutex)
}
// destroy the rwmutex object.
pub fn (mut m RwMutex) destroy() {
res := C.pthread_rwlock_destroy(&m.mutex)
if res == 0 {
return
}
panic(unsafe { tos_clone(&u8(C.strerror(res))) })
}
// Windows SRWLocks have different function to unlock
// So provide two functions here, too, to have a common interface
pub fn (mut m RwMutex) runlock() {
C.pthread_rwlock_unlock(&m.mutex)
}
// unlock the rwmutex object. The rwmutex is released.
pub fn (mut m RwMutex) unlock() {
C.pthread_rwlock_unlock(&m.mutex)
}
// new_semaphore create a new semaphore, with zero initial value.
[inline]
pub fn new_semaphore() &Semaphore {
return new_semaphore_init(0)
}
// new_semaphore_init create a semaphore, with `n` initial value.
pub fn new_semaphore_init(n u32) &Semaphore {
mut sem := &Semaphore{}
sem.init(n)
return sem
}
// init the semaphore, with `n` initial value.
pub fn (mut sem Semaphore) init(n u32) {
C.sem_init(&sem.sem, 0, n)
}
// post increase the semaphore's value by 1.
pub fn (mut sem Semaphore) post() {
C.sem_post(&sem.sem)
}
// wait decrease the semaphore's value by 1. If semaphore's original value is zero, then wait.
pub fn (mut sem Semaphore) wait() {
for {
if C.sem_wait(&sem.sem) == 0 {
@ -153,7 +186,7 @@ pub fn (mut sem Semaphore) wait() {
}
}
// `try_wait()` should return as fast as possible so error handling is only
// try_wait should return as fast as possible so error handling is only
// done when debugging
pub fn (mut sem Semaphore) try_wait() bool {
$if !debug {
@ -174,6 +207,8 @@ pub fn (mut sem Semaphore) try_wait() bool {
}
}
// timed_wait decrease the semaphore's value by 1. If semaphore's original
// value is zero, then wait. If `timeout` return false.
pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
$if macos {
time.sleep(timeout)
@ -202,7 +237,8 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
return false
}
pub fn (sem Semaphore) destroy() {
// destroy the semaphore object.
pub fn (mut sem Semaphore) destroy() {
res := C.sem_destroy(&sem.sem)
if res == 0 {
return

View File

@ -0,0 +1,20 @@
import sync
fn main() {
mut mutex := sync.new_mutex()
mutex.@lock()
mutex.unlock()
mutex.destroy()
mut rwmutex := sync.new_rwmutex()
rwmutex.@rlock()
rwmutex.unlock()
rwmutex.@lock()
rwmutex.unlock()
rwmutex.destroy()
mut sem := sync.new_semaphore()
sem.post()
sem.wait()
sem.destroy()
}