mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
sync: add .try_lock() to mutex/rwmutex, add tests (#20381)
This commit is contained in:
parent
4e5c597569
commit
d7fc66f054
42
vlib/sync/mutex_test.v
Normal file
42
vlib/sync/mutex_test.v
Normal file
@ -0,0 +1,42 @@
|
||||
import sync
|
||||
|
||||
struct Counter {
|
||||
pub mut:
|
||||
i int
|
||||
}
|
||||
|
||||
fn write_10000(mut co Counter, mut mx sync.Mutex) {
|
||||
mx.@lock()
|
||||
co.i = 10000
|
||||
mx.unlock()
|
||||
}
|
||||
|
||||
fn test_mutex() {
|
||||
mut co := &Counter{10086}
|
||||
mut mx := sync.new_mutex()
|
||||
mx.@lock()
|
||||
co.i = 888
|
||||
th := spawn write_10000(mut co, mut mx)
|
||||
mx.unlock() // after mx unlock, thread write_10000 can continue
|
||||
th.wait()
|
||||
mx.destroy()
|
||||
assert co.i == 10000
|
||||
}
|
||||
|
||||
fn test_try_lock_mutex() {
|
||||
// In Windows, try_lock only avalible after Windows 7
|
||||
$if windows {
|
||||
$if !windows_7 ? {
|
||||
return
|
||||
}
|
||||
}
|
||||
mut mx := sync.new_mutex()
|
||||
mx.@lock()
|
||||
try_fail := mx.try_lock()
|
||||
assert try_fail == false
|
||||
mx.unlock()
|
||||
try_sucess := mx.try_lock()
|
||||
assert try_sucess == true
|
||||
mx.unlock() // you must unlock it, after try_lock sucess
|
||||
mx.destroy()
|
||||
}
|
74
vlib/sync/rwmutex_test.v
Normal file
74
vlib/sync/rwmutex_test.v
Normal file
@ -0,0 +1,74 @@
|
||||
import sync
|
||||
import time
|
||||
|
||||
struct Counter {
|
||||
pub mut:
|
||||
i int
|
||||
}
|
||||
|
||||
fn write_10000(mut co Counter, mut mx sync.RwMutex) {
|
||||
mx.@lock()
|
||||
co.i = 10000
|
||||
mx.unlock()
|
||||
}
|
||||
|
||||
fn test_rwmutex() {
|
||||
mut co := &Counter{10086}
|
||||
mut mx := sync.new_rwmutex()
|
||||
mx.@lock()
|
||||
co.i = 888
|
||||
th1 := spawn write_10000(mut co, mut mx)
|
||||
mx.unlock() // after mx unlock, thread write_10000 can continue
|
||||
th1.wait()
|
||||
assert co.i == 10000
|
||||
|
||||
mx.@rlock()
|
||||
th2 := spawn write_10000(mut co, mut mx) // write_10000 will be blocked
|
||||
co.i = 999 // for demo purpose, don't modify data in rlock!
|
||||
time.sleep(1 * time.millisecond)
|
||||
assert co.i == 999
|
||||
mx.runlock() // after rlock released, write_10000 can continue
|
||||
th2.wait()
|
||||
assert co.i == 10000
|
||||
mx.destroy()
|
||||
}
|
||||
|
||||
fn test_try_lock_rwmutex() {
|
||||
// In Windows, try_lock only avalible after Windows 7
|
||||
$if windows {
|
||||
$if !windows_7 ? {
|
||||
return
|
||||
}
|
||||
}
|
||||
mut mx := sync.new_rwmutex()
|
||||
|
||||
// try_rlock will always fail when mx locked
|
||||
mx.@lock()
|
||||
try_fail_reading1 := mx.try_rlock()
|
||||
try_fail_writing1 := mx.try_wlock()
|
||||
assert try_fail_reading1 == false
|
||||
assert try_fail_writing1 == false
|
||||
|
||||
mx.unlock()
|
||||
|
||||
// try_rlock will always sucess when mx unlocked,
|
||||
// multiple try_rlock can apply to the same mx
|
||||
try_sucess_reading2 := mx.try_rlock()
|
||||
try_sucess_reading3 := mx.try_rlock()
|
||||
assert try_sucess_reading2 == true
|
||||
assert try_sucess_reading3 == true
|
||||
|
||||
// if mx is rlocked, then the try_wlock will fail
|
||||
try_fail_writing2 := mx.try_wlock()
|
||||
assert try_fail_writing2 == false
|
||||
|
||||
mx.runlock()
|
||||
mx.runlock() // you must release rlock mutiple times, as it was rlocked multiple times
|
||||
|
||||
// after mx release all rlock, try_wlock will sucess
|
||||
try_sucess_writing3 := mx.try_wlock()
|
||||
assert try_sucess_writing3 == true
|
||||
|
||||
mx.unlock() // you must unlock it, after try_wlock sucess
|
||||
mx.destroy()
|
||||
}
|
@ -12,6 +12,7 @@ import time
|
||||
@[trusted]
|
||||
fn C.pthread_mutex_init(voidptr, voidptr) int
|
||||
fn C.pthread_mutex_lock(voidptr) int
|
||||
fn C.pthread_mutex_trylock(voidptr) int
|
||||
fn C.pthread_mutex_unlock(voidptr) int
|
||||
fn C.pthread_mutex_destroy(voidptr) int
|
||||
fn C.pthread_rwlockattr_init(voidptr) int
|
||||
@ -20,6 +21,8 @@ fn C.pthread_rwlockattr_setpshared(voidptr, int) 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_tryrdlock(voidptr) int
|
||||
fn C.pthread_rwlock_trywrlock(voidptr) int
|
||||
fn C.pthread_rwlock_unlock(voidptr) int
|
||||
fn C.pthread_rwlock_destroy(voidptr) int
|
||||
fn C.pthread_condattr_init(voidptr) int
|
||||
@ -119,6 +122,13 @@ pub fn (mut m Mutex) @lock() {
|
||||
C.pthread_mutex_lock(&m.mutex)
|
||||
}
|
||||
|
||||
// try_lock try to lock the mutex instance and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m Mutex) try_lock() bool {
|
||||
return C.pthread_mutex_trylock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// unlock unlocks the mutex instance. The mutex is released, and one of
|
||||
// the other threads, that were blocked, because they called @lock can continue.
|
||||
@[inline]
|
||||
@ -158,6 +168,20 @@ pub fn (mut m RwMutex) @lock() {
|
||||
C.pthread_rwlock_wrlock(&m.mutex)
|
||||
}
|
||||
|
||||
// try_rlock try to lock the given RwMutex instance for reading and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m RwMutex) try_rlock() bool {
|
||||
return C.pthread_rwlock_tryrdlock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// try_wlock try to lock the given RwMutex instance for writing and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m RwMutex) try_wlock() bool {
|
||||
return C.pthread_rwlock_trywrlock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// destroy frees the resources associated with the rwmutex instance.
|
||||
// Note: the mutex itself is not freed.
|
||||
@[inline]
|
||||
|
@ -16,6 +16,7 @@ $if !android {
|
||||
@[trusted]
|
||||
fn C.pthread_mutex_init(voidptr, voidptr) int
|
||||
fn C.pthread_mutex_lock(voidptr) int
|
||||
fn C.pthread_mutex_trylock(voidptr) int
|
||||
fn C.pthread_mutex_unlock(voidptr) int
|
||||
fn C.pthread_mutex_destroy(voidptr) int
|
||||
fn C.pthread_rwlockattr_init(voidptr) int
|
||||
@ -25,6 +26,8 @@ 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_tryrdlock(voidptr) int
|
||||
fn C.pthread_rwlock_trywrlock(voidptr) int
|
||||
fn C.pthread_rwlock_unlock(voidptr) int
|
||||
fn C.pthread_rwlock_destroy(voidptr) int
|
||||
fn C.sem_init(voidptr, int, u32) int
|
||||
@ -106,6 +109,13 @@ pub fn (mut m Mutex) @lock() {
|
||||
C.pthread_mutex_lock(&m.mutex)
|
||||
}
|
||||
|
||||
// try_lock try to lock the mutex instance and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m Mutex) try_lock() bool {
|
||||
return C.pthread_mutex_trylock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// unlock unlocks the mutex instance. The mutex is released, and one of
|
||||
// the other threads, that were blocked, because they called @lock can continue.
|
||||
@[inline]
|
||||
@ -144,6 +154,20 @@ pub fn (mut m RwMutex) @lock() {
|
||||
C.pthread_rwlock_wrlock(&m.mutex)
|
||||
}
|
||||
|
||||
// try_rlock try to lock the given RwMutex instance for reading and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m RwMutex) try_rlock() bool {
|
||||
return C.pthread_rwlock_tryrdlock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// try_wlock try to lock the given RwMutex instance for writing and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
@[inline]
|
||||
pub fn (mut m RwMutex) try_wlock() bool {
|
||||
return C.pthread_rwlock_trywrlock(&m.mutex) == 0
|
||||
}
|
||||
|
||||
// destroy frees the resources associated with the rwmutex instance.
|
||||
// Note: the mutex itself is not freed.
|
||||
pub fn (mut m RwMutex) destroy() {
|
||||
|
@ -76,6 +76,19 @@ pub fn (mut m Mutex) @lock() {
|
||||
C.AcquireSRWLockExclusive(&m.mx)
|
||||
}
|
||||
|
||||
// try_lock try to lock the mutex instance and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
// NOTE: try_lock require Windows 7 or later. Before Windows 7, it will always return false.
|
||||
// NOTE: To enable try_lock , you should compile your project with `-d windows_7`, like `v . -d windows_7`
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-tryacquiresrwlockexclusive
|
||||
pub fn (mut m Mutex) try_lock() bool {
|
||||
$if windows_7 ? {
|
||||
return C.TryAcquireSRWLockExclusive(&m.mx) != 0
|
||||
} $else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut m Mutex) unlock() {
|
||||
C.ReleaseSRWLockExclusive(&m.mx)
|
||||
}
|
||||
@ -89,6 +102,32 @@ pub fn (mut m RwMutex) @lock() {
|
||||
C.AcquireSRWLockExclusive(&m.mx)
|
||||
}
|
||||
|
||||
// try_rlock try to lock the given RwMutex instance for reading and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
// NOTE: try_rlock require Windows 7 or later. Before Windows 7, it will always return false.
|
||||
// NOTE: To enable try_rlock , you should compile your project with `-d windows_7`, like `v . -d windows_7`
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-tryacquiresrwlockshared
|
||||
pub fn (mut m RwMutex) try_rlock() bool {
|
||||
$if windows_7 ? {
|
||||
return C.TryAcquireSRWLockShared(&m.mx) != 0
|
||||
} $else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// try_wlock try to lock the given RwMutex instance for writing and return immediately.
|
||||
// If the mutex was already locked, it will return false.
|
||||
// NOTE: try_wlock require Windows 7 or later. Before Windows 7, it will always return false.
|
||||
// NOTE: To enable try_wlock , you should compile your project with `-d windows_7`, like `v . -d windows_7`
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-tryacquiresrwlockexclusive
|
||||
pub fn (mut m RwMutex) try_wlock() bool {
|
||||
$if windows_7 ? {
|
||||
return C.TryAcquireSRWLockExclusive(&m.mx) != 0
|
||||
} $else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Windows SRWLocks have different function to unlock
|
||||
// So provide two functions here, too, to have a common interface
|
||||
pub fn (mut m RwMutex) runlock() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user