v2 / vlib / os / filelock / lib_windows.c.v
99 lines · 89 sloc · 2.43 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module filelock
2
3#insert "@VEXEROOT/vlib/os/filelock/filelock_helpers.h"
4
5fn C.DeleteFileW(&u16) bool
6fn C.CreateFileW(&u16, u32, u32, voidptr, u32, u32, voidptr) voidptr
7fn C.CloseHandle(voidptr) bool
8fn C.v_filelock_lock(voidptr, int, int, u64, u64) int
9fn C.v_filelock_unlock(voidptr, u64, u64) int
10
11fn (l &FileLock) open_lock() i64 {
12 if l.target == .file {
13 return open_existing_file(l.name, l.mode)
14 }
15 return open_lockfile(l.name)
16}
17
18fn open_lockfile(path string) i64 {
19 path_wide := path.to_wide()
20 handle := C.CreateFileW(path_wide, C.GENERIC_READ | C.GENERIC_WRITE, 0, 0, C.OPEN_ALWAYS,
21 C.FILE_ATTRIBUTE_NORMAL, 0)
22 return file_handle(handle)
23}
24
25fn open_existing_file(path string, mode LockMode) i64 {
26 path_wide := path.to_wide()
27 access := if mode == .shared { C.GENERIC_READ } else { C.GENERIC_READ | C.GENERIC_WRITE }
28 share_mode := C.FILE_SHARE_READ | C.FILE_SHARE_WRITE | C.FILE_SHARE_DELETE
29 handle := C.CreateFileW(path_wide, access, share_mode, 0, C.OPEN_EXISTING,
30 C.FILE_ATTRIBUTE_NORMAL, 0)
31 return file_handle(handle)
32}
33
34fn file_handle(handle voidptr) i64 {
35 return if handle == voidptr(-1) { -1 } else { i64(handle) }
36}
37
38fn (l &FileLock) lock_handle(handle voidptr, immediate bool) bool {
39 if l.target != .file {
40 return true
41 }
42 return C.v_filelock_lock(handle, int(l.mode == .exclusive), int(immediate), l.start, l.len) == 0
43}
44
45fn (mut l FileLock) close_lock() {
46 if l.fd == -1 {
47 return
48 }
49 handle := voidptr(l.fd)
50 if l.target == .file {
51 C.v_filelock_unlock(handle, l.start, l.len)
52 C.CloseHandle(handle)
53 } else {
54 C.CloseHandle(handle)
55 path_wide := l.name.to_wide()
56 C.DeleteFileW(path_wide)
57 }
58 l.fd = -1
59}
60
61// acquire blocks until the lock is acquired.
62pub fn (mut l FileLock) acquire() ! {
63 if l.fd != -1 {
64 return error_with_code('lock already acquired by this instance', 1)
65 }
66 fd := l.open_lock()
67 if fd == -1 {
68 msg := if l.target == .file {
69 'cannot open file ${l.name}'
70 } else {
71 'cannot create lock file ${l.name}'
72 }
73 return error_with_code(msg, -1)
74 }
75 handle := voidptr(fd)
76 if !l.lock_handle(handle, false) {
77 C.CloseHandle(handle)
78 return error_with_code('cannot lock ${l.name}', -2)
79 }
80 l.fd = fd
81}
82
83// try_acquire tries to acquire the lock without blocking.
84pub fn (mut l FileLock) try_acquire() bool {
85 if l.fd != -1 {
86 return true
87 }
88 fd := l.open_lock()
89 if fd == -1 {
90 return false
91 }
92 handle := voidptr(fd)
93 if !l.lock_handle(handle, true) {
94 C.CloseHandle(handle)
95 return false
96 }
97 l.fd = fd
98 return true
99}
100