More cleanup

This commit is contained in:
2025-09-14 20:17:42 -04:00
parent f39149d516
commit 147edf5c93
16 changed files with 115 additions and 134 deletions

View File

@@ -34,7 +34,9 @@ struct MessageSender {
*
* Thread-safe method that can be called from any thread, including
* pipeline processing threads. The arena is moved into the connection
* to maintain data lifetime until the message is sent.
* to maintain data lifetime until the message is sent. Messages appended
* concurrently may be written in either order, but they will not be
* interleaved.
*
* @param data_parts Span of string_view parts to send (arena-allocated)
* @param arena Arena containing the memory for data_parts string_views
@@ -55,20 +57,21 @@ struct MessageSender {
};
/**
* Represents a single client connection with thread-safe concurrent access.
* Represents a single client connection - the full interface available to the
* io thread and connection handler.
*
* Connection ownership model:
* - Server owns all connections
* - Handlers receive Connection& references, and can keep a WeakRef to
* Connection for async responses.
* - Multiple pipeline threads can safely access connection concurrently
* MessageSender for async responses.
* - Multiple pipeline threads can safely access the MessageSender concurrently
* - I/O thread has exclusive access to socket operations
*
* Threading model:
* - Single mutex protects all connection state
* - Single mutex protects state shared with pipeline threads
* - Pipeline threads call Connection methods (append_message, etc.)
* - I/O thread processes socket events and message queue
* - Pipeline threads manage epoll interests via Connection methods
* - Pipeline threads register epoll write interest via append_message
* - Connection tracks closed state to prevent EBADF errors
*
* Arena allocator usage:
@@ -258,7 +261,7 @@ struct Connection : MessageSender {
*
* Example usage:
* ```cpp
* class HttpHandler : public ConnectionHandler {
* class HttpHandler : ConnectionHandler {
* void on_connection_established(Connection& conn) override {
* // Allocate HTTP state in connection's arena or heap
* auto* state = conn.get_arena().construct<HttpConnectionState>();
@@ -272,8 +275,8 @@ struct Connection : MessageSender {
* }
*
* void on_data_arrived(std::string_view data,
* Ref<Connection>& conn_ptr) override {
* auto* state = static_cast<HttpConnectionState*>(conn_ptr->user_data);
* Connection& conn) override {
* auto* state = static_cast<HttpConnectionState*>(conn.user_data);
* // Use state for protocol processing...
* }
* };
@@ -323,28 +326,25 @@ private:
};
uint32_t write_bytes();
// Direct access methods for Server (must hold mutex)
int getFd() const { return fd_; }
bool has_messages() const { return !message_queue_.empty(); }
size_t getEpollIndex() const { return epoll_index_; }
void close();
// Immutable connection properties
int fd_;
const int64_t id_;
const size_t epoll_index_; // Index of the epoll instance this connection uses
struct sockaddr_storage addr_; // sockaddr_storage handles IPv4/IPv6
ConnectionHandler *const handler_;
WeakRef<Server> server_; // Weak reference to server for safe cleanup
WeakRef<Server> server_; // Weak reference to server for safe epoll_ctl calls
WeakRef<Connection> self_ref_; // WeakRef to self for get_weak_ref()
// Thread-safe state (protected by mutex_)
// state shared with pipeline threads (protected by mutex_)
mutable std::mutex mutex_; // Protects all mutable state
std::deque<Message>
message_queue_; // Queue of messages to send. Protectec by
message_queue_; // Queue of messages to send. Protected by
// mutex_, but if non-empty mutex_ can be
// dropped while server accesses existing elements.
int64_t outgoing_bytes_queued_{0}; // Counter of queued bytes
// Set to a negative number in `close`
int fd_;
#if __has_feature(thread_sanitizer)
void tsan_acquire() { tsan_sync.load(std::memory_order_acquire); }