1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#pragma once
///@file
#include "lix/libutil/error.hh"
#include "lix/libutil/file-descriptor.hh"
#include "lix/libutil/result.hh"
#include "lix/libutil/types.hh"
#include <chrono>
#include <kj/async.h>
#include <kj/common.h>
namespace nix {
/**
* Open (possibly create) a lock file and return the file descriptor.
* -1 is returned if create is false and the lock could not be opened
* because it doesn't exist. Any other error throws an exception.
*/
AutoCloseFD openLockFile(const Path & path, bool create);
enum LockType { ltRead, ltWrite };
void lockFile(int fd, LockType lockType, NeverAsync = {});
kj::Promise<Result<void>> lockFileAsync(int fd, LockType lockType);
bool tryLockFile(int fd, LockType lockType);
void unlockFile(int fd);
class PathLock
{
friend kj::Promise<Result<PathLock>> lockPathAsync(const Path & path, std::string_view waitMsg);
friend PathLock lockPath(const Path & path, std::string_view waitMsg, NeverAsync);
friend std::optional<PathLock> tryLockPath(const Path & path);
AutoCloseFD fd;
Path path;
PathLock(AutoCloseFD fd, const Path & path): fd(std::move(fd)), path(path) {}
static std::optional<PathLock>
lockImpl(const Path & path, std::string_view waitMsg, bool wait, NeverAsync = {});
public:
PathLock(PathLock &&) = default;
PathLock & operator=(PathLock &&) = default;
~PathLock();
void unlock();
};
kj::Promise<Result<PathLock>> lockPathAsync(const Path & path, std::string_view waitMsg = "");
PathLock lockPath(const Path & path, std::string_view waitMsg = "", NeverAsync = {});
std::optional<PathLock> tryLockPath(const Path & path);
using PathLocks = std::list<PathLock>;
PathLocks lockPaths(const PathSet & paths, std::string_view waitMsg = "", NeverAsync = {});
std::optional<PathLocks> tryLockPaths(const PathSet & paths);
class FdLock
{
struct Unlocker
{
void operator()(AutoCloseFD * fd)
{
try {
unlockFile(fd->get());
} catch (SysError &) {
ignoreExceptionInDestructor();
}
}
};
std::unique_ptr<AutoCloseFD, Unlocker> fd;
explicit FdLock(AutoCloseFD & fd): fd(&fd) {}
public:
static constexpr struct DontWait { explicit DontWait() = default; } dont_wait;
FdLock(AutoCloseFD & fd, LockType lockType, DontWait);
FdLock(AutoCloseFD & fd, LockType lockType, std::string_view waitMsg, NeverAsync = {});
static kj::Promise<Result<FdLock>>
lockAsync(AutoCloseFD & fd, LockType lockType, std::string_view waitMsg);
bool valid() const { return bool(fd); }
};
}
|