Add thread-local caches for file locks and handles in fd_pool
This commit is contained in:
@@ -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