1 | #pragma once |
---|---|
2 | |
3 | #include "taichi/common/cleanup.h" |
4 | #include "taichi/common/core.h" |
5 | #include <thread> |
6 | |
7 | #if defined(TI_PLATFORM_WINDOWS) |
8 | #include <io.h> |
9 | #include <fcntl.h> |
10 | #else // POSIX |
11 | #include <sys/types.h> |
12 | #include <sys/stat.h> |
13 | #include <fcntl.h> |
14 | #include <unistd.h> |
15 | #endif |
16 | |
17 | namespace taichi { |
18 | |
19 | inline bool try_lock_with_file(const std::string &path) { |
20 | int fd{-1}; |
21 | #if defined(TI_PLATFORM_WINDOWS) |
22 | // See |
23 | // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/sopen-s-wsopen-s |
24 | ::_sopen_s(&fd, path.c_str(), _O_CREAT | _O_EXCL, _SH_DENYNO, |
25 | _S_IREAD | _S_IWRITE); |
26 | if (fd != -1) |
27 | ::_close(fd); |
28 | #else |
29 | // See https://www.man7.org/linux/man-pages/man2/open.2.html |
30 | fd = ::open(path.c_str(), O_CREAT | O_EXCL, |
31 | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); |
32 | if (fd != -1) |
33 | ::close(fd); |
34 | #endif |
35 | return fd != -1; |
36 | } |
37 | |
38 | inline bool unlock_with_file(const std::string &path) { |
39 | return std::remove(path.c_str()) == 0; |
40 | } |
41 | |
42 | inline bool lock_with_file(const std::string &path, |
43 | int ms_delay = 50, |
44 | int try_count = 5) { |
45 | if (try_lock_with_file(path)) { |
46 | return true; |
47 | } |
48 | for (int i = 1; i < try_count; ++i) { |
49 | std::chrono::milliseconds delay{ms_delay}; |
50 | std::this_thread::sleep_for(delay); |
51 | if (try_lock_with_file(path)) { |
52 | return true; |
53 | } |
54 | } |
55 | return false; |
56 | } |
57 | |
58 | inline RaiiCleanup make_unlocker(const std::string &path) { |
59 | return make_cleanup([&path]() { |
60 | if (!unlock_with_file(path)) { |
61 | TI_WARN( |
62 | "Unlock {} failed. You can remove this .lock file manually and try " |
63 | "again.", |
64 | path); |
65 | } |
66 | }); |
67 | } |
68 | |
69 | } // namespace taichi |
70 |