Document per-connection locking strategy
This commit is contained in:
@@ -201,57 +201,6 @@ struct Connection : MessageSender {
|
||||
*/
|
||||
int64_t get_id() const { return id_; }
|
||||
|
||||
/**
|
||||
* @brief Get the number of bytes queued for transmission.
|
||||
*
|
||||
* Returns the total number of bytes in all messages currently
|
||||
* queued for transmission to the client. This includes all data added via
|
||||
* append_message() that has not yet been sent over the network.
|
||||
*
|
||||
* @return Total bytes queued for transmission
|
||||
*
|
||||
* @warning Thread Safety: Only call from the thread that currently owns this
|
||||
* connection. Concurrent access to the message queue is not thread-safe.
|
||||
*
|
||||
* @note Performance: This method uses an O(1) counter for fast retrieval
|
||||
* in release builds. In debug builds, validates counter accuracy.
|
||||
*
|
||||
* @note The count decreases as the server sends data via writeBytes() and
|
||||
* removes completed messages from the queue.
|
||||
*
|
||||
* Use cases:
|
||||
* ```cpp
|
||||
* // Check if all data has been sent
|
||||
* if (conn->outgoing_bytes_queued() == 0) {
|
||||
* conn->reset(); // Safe to reset arena
|
||||
* }
|
||||
*
|
||||
* // Implement backpressure
|
||||
* if (conn->outgoing_bytes_queued() > MAX_BUFFER_SIZE) {
|
||||
* // Stop adding more data until queue drains
|
||||
* }
|
||||
*
|
||||
* // Logging/monitoring
|
||||
* metrics.recordQueueDepth(conn->get_id(), conn->outgoing_bytes_queued());
|
||||
* ```
|
||||
*/
|
||||
int64_t outgoing_bytes_queued() const {
|
||||
std::lock_guard lock(mutex_);
|
||||
#ifndef NDEBUG
|
||||
// Debug build: validate counter accuracy
|
||||
int64_t computed_total = 0;
|
||||
for (const auto &message : message_queue_) {
|
||||
for (const auto &part : message.data_parts) {
|
||||
computed_total += part.size();
|
||||
}
|
||||
}
|
||||
assert(
|
||||
outgoing_bytes_queued_ == computed_total &&
|
||||
"outgoing_bytes_queued_ counter is out of sync with actual queue size");
|
||||
#endif
|
||||
return outgoing_bytes_queued_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Protocol-specific data pointer for handler use.
|
||||
*
|
||||
@@ -347,19 +296,14 @@ private:
|
||||
WeakRef<Server> server_; // Weak reference to server for safe epoll_ctl calls
|
||||
WeakRef<Connection> self_ref_; // WeakRef to self for get_weak_ref()
|
||||
|
||||
// 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. 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
|
||||
std::deque<PendingResponse>
|
||||
pending_response_queue_; // Responses awaiting protocol processing
|
||||
// Only accessed from io thread
|
||||
std::deque<Message> message_queue_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
ConnectionShutdown shutdown_requested_{
|
||||
ConnectionShutdown::None}; // Shutdown mode requested
|
||||
// Set to a negative number in `close`
|
||||
int fd_;
|
||||
ConnectionShutdown::None}; // Protected by mutex_
|
||||
std::deque<PendingResponse> pending_response_queue_; // Protected by mutex_
|
||||
int fd_; // Protected by mutex_
|
||||
|
||||
#if __has_feature(thread_sanitizer)
|
||||
void tsan_acquire() { tsan_sync.load(std::memory_order_acquire); }
|
||||
|
||||
Reference in New Issue
Block a user