Fixed windows deadlocks, performance is shit tho
This commit is contained in:
@@ -22,6 +22,8 @@ public:
|
||||
|
||||
private:
|
||||
std::string filePath;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
Mode mode;
|
||||
bool locked = false;
|
||||
|
||||
@@ -55,11 +57,15 @@ private:
|
||||
|
||||
void acquire() {
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
DWORD flags = (mode == Mode::Exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
|
||||
flags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
OVERLAPPED overlapped = {}; // Proper zero-initialization
|
||||
overlapped.Offset = static_cast<DWORD>(offset & 0xFFFFFFFF);
|
||||
overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
|
||||
|
||||
if (!LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped)) {
|
||||
DWORD length_low = static_cast<DWORD>(length & 0xFFFFFFFF);
|
||||
DWORD length_high = static_cast<DWORD>(length >> 32);
|
||||
DWORD flags = (mode == Mode::Exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
|
||||
|
||||
if (!LockFileEx(handle, flags, 0, length_low, length_high, &overlapped)) {
|
||||
throw std::runtime_error("Failed to acquire file lock");
|
||||
}
|
||||
locked = true;
|
||||
@@ -68,8 +74,14 @@ private:
|
||||
void release() {
|
||||
if (locked) {
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
OVERLAPPED overlapped = {};
|
||||
overlapped.Offset = static_cast<DWORD>(offset & 0xFFFFFFFF);
|
||||
overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
|
||||
|
||||
DWORD length_low = static_cast<DWORD>(length & 0xFFFFFFFF);
|
||||
DWORD length_high = static_cast<DWORD>(length >> 32);
|
||||
|
||||
UnlockFileEx(handle, 0, length_low, length_high, &overlapped);
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
@@ -94,9 +106,15 @@ private:
|
||||
|
||||
void acquire() {
|
||||
int fd = getOrOpenFD(filePath);
|
||||
int operation = (mode == Mode::Exclusive) ? LOCK_EX : LOCK_SH;
|
||||
|
||||
if (flock(fd, operation) == -1) {
|
||||
struct flock lock_info;
|
||||
lock_info.l_type = (mode == Mode::Exclusive) ? F_WRLCK : F_RDLCK;
|
||||
lock_info.l_whence = SEEK_SET;
|
||||
lock_info.l_start = offset;
|
||||
lock_info.l_len = length;
|
||||
lock_info.l_pid = 0;
|
||||
|
||||
if (fcntl(fd, F_SETLKW, &lock_info) == -1) {
|
||||
throw std::runtime_error("Failed to acquire file lock");
|
||||
}
|
||||
locked = true;
|
||||
@@ -105,16 +123,24 @@ private:
|
||||
void release() {
|
||||
if (locked) {
|
||||
int fd = getOrOpenFD(filePath);
|
||||
flock(fd, LOCK_UN);
|
||||
|
||||
struct flock lock_info;
|
||||
lock_info.l_type = F_UNLCK;
|
||||
lock_info.l_whence = SEEK_SET;
|
||||
lock_info.l_start = offset;
|
||||
lock_info.l_len = length;
|
||||
lock_info.l_pid = 0;
|
||||
|
||||
fcntl(fd, F_SETLK, &lock_info);
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructor accepts offset/length for API compatibility (unused with flock)
|
||||
SweepstoreFileLock(const std::string& path, uint64_t, uint64_t, Mode m)
|
||||
: filePath(path), mode(m) {}
|
||||
// Constructor accepts offset/length for byte-range locking
|
||||
SweepstoreFileLock(const std::string& path, uint64_t off, uint64_t len, Mode m)
|
||||
: filePath(path), offset(off), length(len), mode(m) {}
|
||||
|
||||
~SweepstoreFileLock() { release(); }
|
||||
|
||||
@@ -131,32 +157,44 @@ public:
|
||||
}
|
||||
|
||||
// Check if file is currently locked (non-blocking test)
|
||||
bool isLocked() const {
|
||||
bool isLocked() {
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
OVERLAPPED overlapped = {};
|
||||
overlapped.Offset = static_cast<DWORD>(offset & 0xFFFFFFFF);
|
||||
overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
|
||||
|
||||
DWORD length_low = static_cast<DWORD>(length & 0xFFFFFFFF);
|
||||
DWORD length_high = static_cast<DWORD>(length >> 32);
|
||||
DWORD flags = (mode == Mode::Exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
|
||||
flags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
|
||||
// Try non-blocking lock
|
||||
if (!LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped)) {
|
||||
if (!LockFileEx(handle, flags, 0, length_low, length_high, &overlapped)) {
|
||||
return true; // Already locked
|
||||
}
|
||||
|
||||
// Got the lock, release immediately
|
||||
UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
UnlockFileEx(handle, 0, length_low, length_high, &overlapped);
|
||||
return false;
|
||||
#else
|
||||
int fd = getOrOpenFD(filePath);
|
||||
int operation = (mode == Mode::Exclusive) ? LOCK_EX : LOCK_SH;
|
||||
|
||||
struct flock lock_info;
|
||||
lock_info.l_type = (mode == Mode::Exclusive) ? F_WRLCK : F_RDLCK;
|
||||
lock_info.l_whence = SEEK_SET;
|
||||
lock_info.l_start = offset;
|
||||
lock_info.l_len = length;
|
||||
lock_info.l_pid = 0;
|
||||
|
||||
// Try non-blocking lock
|
||||
if (flock(fd, operation | LOCK_NB) == -1) {
|
||||
if (fcntl(fd, F_SETLK, &lock_info) == -1) {
|
||||
return true; // Already locked
|
||||
}
|
||||
|
||||
// Got the lock, release immediately
|
||||
flock(fd, LOCK_UN);
|
||||
lock_info.l_type = F_UNLCK;
|
||||
fcntl(fd, F_SETLK, &lock_info);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user