Add thread-local caches for file locks and handles in fd_pool

This commit is contained in:
ImBenji
2025-12-04 20:33:06 +00:00
parent 6e81375d7f
commit 4bace6f681
4 changed files with 74 additions and 2 deletions

View File

@@ -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

View 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

View File

@@ -57,7 +57,7 @@ public:
}
);
};
}
};
Proxy operator[](const std::string& key) {

View File

@@ -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