Files
weaseldb/src/connection_registry.cpp

63 lines
1.9 KiB
C++

#include "connection_registry.hpp"
#include "connection.hpp"
#include <atomic>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
ConnectionRegistry::ConnectionRegistry() : connections_(nullptr), max_fds_(0) {
// Get the process file descriptor limit
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) {
perror("getrlimit");
std::abort();
}
max_fds_ = rlim.rlim_cur;
// Calculate size rounded up to page boundary
size_t array_size = max_fds_ * sizeof(Connection *);
size_t page_size = getpagesize();
size_t aligned_size = (array_size + page_size - 1) & ~(page_size - 1);
// Allocate virtual address space using mmap
// MAP_ANONYMOUS provides zero-initialized pages on-demand (lazy allocation)
connections_ = static_cast<std::atomic<Connection *> *>(
mmap(nullptr, aligned_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
if (connections_ == MAP_FAILED) {
perror("mmap");
std::abort();
}
// Store aligned size for munmap
aligned_size_ = aligned_size;
}
ConnectionRegistry::~ConnectionRegistry() {
if (connections_ != nullptr) {
for (int fd = 0; fd < static_cast<int>(max_fds_); ++fd) {
delete connections_[fd].load(std::memory_order_relaxed);
}
if (munmap(connections_, aligned_size_) == -1) {
perror("munmap");
}
}
}
void ConnectionRegistry::store(int fd, std::unique_ptr<Connection> connection) {
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
std::abort();
}
// Release ownership from unique_ptr and store raw pointer
connections_[fd].store(connection.release(), std::memory_order_release);
}
std::unique_ptr<Connection> ConnectionRegistry::remove(int fd) {
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
std::abort();
}
return std::unique_ptr<Connection>(
connections_[fd].exchange(nullptr, std::memory_order_acquire));
}