mirror of
https://github.com/esphome/esphome.git
synced 2026-09-01 02:26:01 +00:00
[api] Add single-buffer write_raw_slow_ overload for cold paths
Cold paths (write_frame_, bad indicator) no longer need to construct an iovec just to call the slow path. The single-buffer overload wraps in iovec internally, keeping call sites clean and avoiding iovec setup in the caller's stack frame.
This commit is contained in:
@@ -112,8 +112,13 @@ APIError APIFrameHelper::drain_overflow_and_handle_errors_() {
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
// Write data to socket, overflow to backlog buffer if LWIP TCP send buffer is full.
|
||||
// Slow path: handles partial writes, errors, and overflow buffering.
|
||||
// Single-buffer slow path: wraps data in iovec and delegates to the iovec slow path.
|
||||
APIError APIFrameHelper::write_raw_slow_(const void *data, uint16_t len, ssize_t sent) {
|
||||
struct iovec iov = {const_cast<void *>(data), len};
|
||||
return this->write_raw_slow_(&iov, 1, len, sent);
|
||||
}
|
||||
|
||||
// Multi-buffer slow path: handles partial writes, errors, and overflow buffering.
|
||||
// Called when the inline fast path in the header couldn't complete the write.
|
||||
// sent == -1 means either the fast path write returned -1, or there was overflow backlog.
|
||||
APIError APIFrameHelper::write_raw_slow_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, ssize_t sent) {
|
||||
|
||||
@@ -199,8 +199,7 @@ class APIFrameHelper {
|
||||
if (sent == static_cast<ssize_t>(len)) [[likely]]
|
||||
return APIError::OK;
|
||||
}
|
||||
struct iovec iov = {const_cast<void *>(data), len};
|
||||
return this->write_raw_slow_(&iov, 1, len, sent);
|
||||
return this->write_raw_slow_(data, len, sent);
|
||||
}
|
||||
// Write multiple iovec buffers to the socket (inlined fast path)
|
||||
inline APIError ESPHOME_ALWAYS_INLINE write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len) {
|
||||
@@ -213,7 +212,8 @@ class APIFrameHelper {
|
||||
}
|
||||
return this->write_raw_slow_(iov, iovcnt, total_write_len, sent);
|
||||
}
|
||||
// Slow path (out-of-line): handle partial writes, errors, overflow buffering
|
||||
// Slow paths (out-of-line): handle partial writes, errors, overflow buffering
|
||||
APIError write_raw_slow_(const void *data, uint16_t len, ssize_t sent);
|
||||
APIError write_raw_slow_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, ssize_t sent);
|
||||
|
||||
// Socket ownership (4 bytes on 32-bit, 8 bytes on 64-bit)
|
||||
|
||||
@@ -539,13 +539,13 @@ APIError APINoiseFrameHelper::write_frame_(const uint8_t *data, uint16_t len) {
|
||||
header[1] = (uint8_t) (len >> 8);
|
||||
header[2] = (uint8_t) len;
|
||||
|
||||
// Handshake-only path — use slow path directly to avoid inlining write_raw_ fast path
|
||||
if (len == 0) {
|
||||
return this->write_raw_slow_(header, 3, -1);
|
||||
}
|
||||
// Handshake path — use iovec slow path directly to avoid inlining write_raw_ fast path
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = header;
|
||||
iov[0].iov_len = 3;
|
||||
if (len == 0) {
|
||||
return this->write_raw_slow_(iov, 1, 3, -1);
|
||||
}
|
||||
iov[1].iov_base = const_cast<uint8_t *>(data);
|
||||
iov[1].iov_len = len;
|
||||
|
||||
|
||||
@@ -219,15 +219,11 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
"Bad indicator byte";
|
||||
char msg[INDICATOR_MSG_SIZE];
|
||||
memcpy_P(msg, MSG_PROGMEM, INDICATOR_MSG_SIZE);
|
||||
// Error path — use slow path directly to avoid inlining write_raw_ fast path
|
||||
struct iovec iov = {msg, INDICATOR_MSG_SIZE};
|
||||
this->write_raw_slow_(&iov, 1, INDICATOR_MSG_SIZE, -1);
|
||||
this->write_raw_slow_(msg, INDICATOR_MSG_SIZE, -1);
|
||||
#else
|
||||
static const char MSG[] = "\x00"
|
||||
"Bad indicator byte";
|
||||
// Error path — use slow path directly to avoid inlining write_raw_ fast path
|
||||
struct iovec iov = {const_cast<char *>(MSG), INDICATOR_MSG_SIZE};
|
||||
this->write_raw_slow_(&iov, 1, INDICATOR_MSG_SIZE, -1);
|
||||
this->write_raw_slow_(MSG, INDICATOR_MSG_SIZE, -1);
|
||||
#endif
|
||||
}
|
||||
return aerr;
|
||||
|
||||
Reference in New Issue
Block a user