Add thread-local caches for file locks and handles in fd_pool
This commit is contained in:
@@ -20,7 +20,6 @@ add_executable(main
|
||||
src/Public/sweepstore/concurrency.h
|
||||
src/Private/sweepstore/concurrency.cpp
|
||||
src/Public/sweepstore/utils/file_lock.h
|
||||
src/Private/sweepstore/utils/fd_pool.h
|
||||
src/Private/sweepstore/utils/fd_pool.cpp
|
||||
src/Public/sweepstore/utils/file_handle.h
|
||||
src/Private/sweepstore/utils/file_handle.cpp
|
||||
|
||||
7
cpp/src/Private/sweepstore/utils/file_lock.cpp
Normal file
7
cpp/src/Private/sweepstore/utils/file_lock.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "sweepstore/utils/file_lock.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
thread_local std::unordered_map<std::string, HANDLE> SweepstoreFileLock::handleCache;
|
||||
#else
|
||||
thread_local std::unordered_map<std::string, int> SweepstoreFileLock::fdCache;
|
||||
#endif
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Proxy operator[](const std::string& key) {
|
||||
|
||||
@@ -25,6 +25,55 @@ private:
|
||||
Mode mode;
|
||||
bool locked = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Thread-local HANDLE cache for Windows
|
||||
static thread_local std::unordered_map<std::string, HANDLE> handleCache;
|
||||
|
||||
static HANDLE getOrOpenHandle(const std::string& path) {
|
||||
auto it = handleCache.find(path);
|
||||
if (it != handleCache.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
HANDLE handle = CreateFileA(
|
||||
path.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
throw std::runtime_error("Failed to open file for locking: " + path);
|
||||
}
|
||||
|
||||
handleCache[path] = handle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void acquire() {
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
DWORD flags = (mode == Mode::Exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
|
||||
flags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
|
||||
if (!LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped)) {
|
||||
throw std::runtime_error("Failed to acquire file lock");
|
||||
}
|
||||
locked = true;
|
||||
}
|
||||
|
||||
void release() {
|
||||
if (locked) {
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Thread-local FD cache - each thread has its own FD per file
|
||||
static thread_local std::unordered_map<std::string, int> fdCache;
|
||||
|
||||
@@ -60,6 +109,7 @@ private:
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructor accepts offset/length for API compatibility (unused with flock)
|
||||
@@ -82,6 +132,21 @@ public:
|
||||
|
||||
// Check if file is currently locked (non-blocking test)
|
||||
bool isLocked() const {
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = getOrOpenHandle(filePath);
|
||||
OVERLAPPED overlapped = {0};
|
||||
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)) {
|
||||
return true; // Already locked
|
||||
}
|
||||
|
||||
// Got the lock, release immediately
|
||||
UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped);
|
||||
return false;
|
||||
#else
|
||||
int fd = getOrOpenFD(filePath);
|
||||
int operation = (mode == Mode::Exclusive) ? LOCK_EX : LOCK_SH;
|
||||
|
||||
@@ -93,6 +158,7 @@ public:
|
||||
// Got the lock, release immediately
|
||||
flock(fd, LOCK_UN);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// RAII helper for scoped locking
|
||||
|
||||
Reference in New Issue
Block a user