100 lines
2.4 KiB
V
100 lines
2.4 KiB
V
module filelock
|
|
|
|
#insert "@VEXEROOT/vlib/os/filelock/filelock_helpers.h"
|
|
|
|
fn C.DeleteFileW(&u16) bool
|
|
fn C.CreateFileW(&u16, u32, u32, voidptr, u32, u32, voidptr) voidptr
|
|
fn C.CloseHandle(voidptr) bool
|
|
fn C.v_filelock_lock(voidptr, int, int, u64, u64) int
|
|
fn C.v_filelock_unlock(voidptr, u64, u64) int
|
|
|
|
fn (l &FileLock) open_lock() i64 {
|
|
if l.target == .file {
|
|
return open_existing_file(l.name, l.mode)
|
|
}
|
|
return open_lockfile(l.name)
|
|
}
|
|
|
|
fn open_lockfile(path string) i64 {
|
|
path_wide := path.to_wide()
|
|
handle := C.CreateFileW(path_wide, C.GENERIC_READ | C.GENERIC_WRITE, 0, 0, C.OPEN_ALWAYS,
|
|
C.FILE_ATTRIBUTE_NORMAL, 0)
|
|
return file_handle(handle)
|
|
}
|
|
|
|
fn open_existing_file(path string, mode LockMode) i64 {
|
|
path_wide := path.to_wide()
|
|
access := if mode == .shared { C.GENERIC_READ } else { C.GENERIC_READ | C.GENERIC_WRITE }
|
|
share_mode := C.FILE_SHARE_READ | C.FILE_SHARE_WRITE | C.FILE_SHARE_DELETE
|
|
handle := C.CreateFileW(path_wide, access, share_mode, 0, C.OPEN_EXISTING,
|
|
C.FILE_ATTRIBUTE_NORMAL, 0)
|
|
return file_handle(handle)
|
|
}
|
|
|
|
fn file_handle(handle voidptr) i64 {
|
|
return if handle == voidptr(-1) { -1 } else { i64(handle) }
|
|
}
|
|
|
|
fn (l &FileLock) lock_handle(handle voidptr, immediate bool) bool {
|
|
if l.target != .file {
|
|
return true
|
|
}
|
|
return C.v_filelock_lock(handle, int(l.mode == .exclusive), int(immediate), l.start, l.len) == 0
|
|
}
|
|
|
|
fn (mut l FileLock) close_lock() {
|
|
if l.fd == -1 {
|
|
return
|
|
}
|
|
handle := voidptr(l.fd)
|
|
if l.target == .file {
|
|
C.v_filelock_unlock(handle, l.start, l.len)
|
|
C.CloseHandle(handle)
|
|
} else {
|
|
C.CloseHandle(handle)
|
|
path_wide := l.name.to_wide()
|
|
C.DeleteFileW(path_wide)
|
|
}
|
|
l.fd = -1
|
|
}
|
|
|
|
// acquire blocks until the lock is acquired.
|
|
pub fn (mut l FileLock) acquire() ! {
|
|
if l.fd != -1 {
|
|
return error_with_code('lock already acquired by this instance', 1)
|
|
}
|
|
fd := l.open_lock()
|
|
if fd == -1 {
|
|
msg := if l.target == .file {
|
|
'cannot open file ${l.name}'
|
|
} else {
|
|
'cannot create lock file ${l.name}'
|
|
}
|
|
return error_with_code(msg, -1)
|
|
}
|
|
handle := voidptr(fd)
|
|
if !l.lock_handle(handle, false) {
|
|
C.CloseHandle(handle)
|
|
return error_with_code('cannot lock ${l.name}', -2)
|
|
}
|
|
l.fd = fd
|
|
}
|
|
|
|
// try_acquire tries to acquire the lock without blocking.
|
|
pub fn (mut l FileLock) try_acquire() bool {
|
|
if l.fd != -1 {
|
|
return true
|
|
}
|
|
fd := l.open_lock()
|
|
if fd == -1 {
|
|
return false
|
|
}
|
|
handle := voidptr(fd)
|
|
if !l.lock_handle(handle, true) {
|
|
C.CloseHandle(handle)
|
|
return false
|
|
}
|
|
l.fd = fd
|
|
return true
|
|
}
|