Simplify connection registry
This commit is contained in:
@@ -12,46 +12,45 @@ ConnectionRegistry::ConnectionRegistry() : connections_(nullptr), max_fds_(0) {
|
||||
}
|
||||
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
|
||||
// This reserves virtual memory but doesn't allocate physical pages until
|
||||
// touched
|
||||
// MAP_ANONYMOUS provides zero-initialized pages on-demand (lazy allocation)
|
||||
connections_ = static_cast<Connection **>(
|
||||
mmap(nullptr, max_fds_ * sizeof(Connection *), PROT_READ | PROT_WRITE,
|
||||
mmap(nullptr, aligned_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
|
||||
if (connections_ == MAP_FAILED) {
|
||||
throw std::runtime_error("Failed to mmap for connection registry");
|
||||
}
|
||||
|
||||
// Initialize all pointers to null
|
||||
// This will cause physical pages to be allocated on-demand
|
||||
memset(connections_, 0, max_fds_ * sizeof(Connection *));
|
||||
// Store aligned size for munmap
|
||||
aligned_size_ = aligned_size;
|
||||
}
|
||||
|
||||
ConnectionRegistry::~ConnectionRegistry() {
|
||||
if (connections_ != MAP_FAILED && connections_ != nullptr) {
|
||||
munmap(connections_, max_fds_ * sizeof(Connection *));
|
||||
if (connections_ != nullptr) {
|
||||
for (size_t fd = 0; fd < max_fds_; ++fd) {
|
||||
delete connections_[fd];
|
||||
}
|
||||
munmap(connections_, aligned_size_);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionRegistry::store(int fd, std::unique_ptr<Connection> connection) {
|
||||
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
|
||||
return; // Invalid fd - silently ignore to avoid crashes
|
||||
abort();
|
||||
}
|
||||
// Release ownership from unique_ptr and store raw pointer
|
||||
connections_[fd] = connection.release();
|
||||
}
|
||||
|
||||
bool ConnectionRegistry::has(int fd) const {
|
||||
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
|
||||
return false; // Invalid fd
|
||||
}
|
||||
return connections_[fd] != nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Connection> ConnectionRegistry::remove(int fd) {
|
||||
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
|
||||
return nullptr; // Invalid fd
|
||||
abort();
|
||||
}
|
||||
|
||||
Connection *conn = connections_[fd];
|
||||
@@ -59,25 +58,3 @@ std::unique_ptr<Connection> ConnectionRegistry::remove(int fd) {
|
||||
// Transfer ownership back to unique_ptr
|
||||
return std::unique_ptr<Connection>(conn);
|
||||
}
|
||||
|
||||
void ConnectionRegistry::shutdown_cleanup() {
|
||||
// Iterate through all possible file descriptors and clean up any connections
|
||||
// Following the critical ordering: remove -> delete (destructor handles
|
||||
// close)
|
||||
size_t connections_found = 0;
|
||||
for (size_t fd = 0; fd < max_fds_; ++fd) {
|
||||
Connection *conn = connections_[fd];
|
||||
if (conn != nullptr) {
|
||||
connections_found++;
|
||||
// Step 1: Remove from registry (set to null)
|
||||
connections_[fd] = nullptr;
|
||||
|
||||
// Steps 2 & 3: Delete the connection object (destructor handles closing
|
||||
// fd)
|
||||
delete conn;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: In normal shutdown, this should be 0 since all connections
|
||||
// should have been properly cleaned up during normal operation
|
||||
}
|
||||
Reference in New Issue
Block a user