Add Connection::arena

This commit is contained in:
2025-08-19 11:51:44 -04:00
parent 1141251002
commit 5dc800a088

View File

@@ -1,3 +1,4 @@
#include "arena_allocator.hpp"
#include "config.hpp"
#include <atomic>
#include <cassert>
@@ -130,6 +131,7 @@ struct Connection {
const int fd;
const int64_t id;
struct sockaddr_storage addr; // sockaddr_storage handles IPv4/IPv6
ArenaAllocator arena;
Connection(struct sockaddr_storage addr, int fd, int64_t id)
: fd(fd), id(id), addr(addr) {
@@ -145,15 +147,24 @@ struct Connection {
}
}
struct Task {
std::string s;
bool closeConnection{false};
struct Message {
// Owned by Connection::arena
std::string_view s;
int written = 0;
};
std::deque<Message, ArenaStlAllocator<Message>> messages{
ArenaStlAllocator<Message>{&arena}};
// Copies s into arena, and appends to messages
void appendMessage(std::string_view s) {
char *arena_str = arena.allocate<char>(s.size());
std::memcpy(arena_str, s.data(), s.size());
messages.emplace_back(std::string_view(arena_str, s.size()), 0);
}
// Whether or not to close the connection after completing writing the
// response
bool closeConnection{false};
std::deque<Task> tasks;
void readBytes(size_t max_request_size) {
bool readBytes(size_t max_request_size) {
// Use smaller buffer size but respect max request size
// TODO revisit
size_t buf_size = std::min(size_t(4096), max_request_size);
@@ -165,28 +176,23 @@ struct Connection {
continue;
}
if (errno == EAGAIN) {
return;
return false;
}
perror("read");
goto close_connection;
return true;
}
if (r == 0) {
goto close_connection;
return true;
}
// "pump parser"
// TODO revisit
tasks.emplace_back(std::string{buf.data(), size_t(r)});
appendMessage({buf.data(), size_t(r)});
}
close_connection:
tasks.emplace_back(std::string{}, true);
}
bool writeBytes() {
while (!tasks.empty()) {
auto &front = tasks.front();
if (front.closeConnection) {
return true;
}
while (!messages.empty()) {
auto &front = messages.front();
int w;
for (;;) {
w = write(fd, front.s.data() + front.written,
@@ -206,10 +212,12 @@ struct Connection {
assert(w != 0);
front.written += w;
if (front.written == int(front.s.size())) {
tasks.pop_front();
messages.pop_front();
}
}
return false;
assert(messages.empty());
arena.reset();
return closeConnection;
}
// This is necessary because tsan doesn't (yet?) understand that there's a
@@ -346,8 +354,16 @@ int main(int argc, char *argv[]) {
continue;
}
// When we register our epoll interest, if we have something to
// write, we write. Otherwise we read.
assert(!((events[i].events & EPOLLIN) &&
(events[i].events & EPOLLOUT)));
if (events[i].events & EPOLLIN) {
conn->readBytes(max_request_size);
bool done = conn->readBytes(max_request_size);
if (done) {
continue;
}
}
if (events[i].events & EPOLLOUT) {
@@ -357,7 +373,7 @@ int main(int argc, char *argv[]) {
}
}
if (conn->tasks.empty()) {
if (conn->messages.empty()) {
events[i].events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP;
} else {
events[i].events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP;