* @brief 将队列中所有条目输出至串口 * * 使用 atomic_flag 实现非阻塞 try-lock,同一时刻仅一个核心执行排空, * 其他核心直接返回,等待下次调用时再排空。 */
| 96 | * 其他核心直接返回,等待下次调用时再排空。 |
| 97 | */ |
| 98 | inline auto TryDrain() -> void { |
| 99 | // 非阻塞 try-lock:若其他核心正在排空则立即返回 |
| 100 | if (drain_flag.test_and_set(std::memory_order_acquire)) { |
| 101 | return; |
| 102 | } |
| 103 | |
| 104 | // 若有丢弃条目则上报 |
| 105 | auto dropped = dropped_count.exchange(0, std::memory_order_relaxed); |
| 106 | if (dropped > 0) { |
| 107 | char drop_buf[64]; |
| 108 | auto* end = etl::format_to_n(drop_buf, sizeof(drop_buf) - 1, |
| 109 | "\033[31m[LOG] dropped {} entries\033[0m\n", |
| 110 | static_cast<uint64_t>(dropped)); |
| 111 | *end = '\0'; |
| 112 | PutStr(drop_buf); |
| 113 | } |
| 114 | |
| 115 | // 排空循环 |
| 116 | auto printer_core = cpu_io::GetCurrentCoreId(); |
| 117 | LogEntry entry{}; |
| 118 | while (log_queue.pop(entry)) { |
| 119 | // 格式: [id][core_id1 core_id2 LEVEL] msg |
| 120 | char hdr_buf[48]; |
| 121 | auto* hdr_end = |
| 122 | etl::format_to_n(hdr_buf, sizeof(hdr_buf) - 1, "[{}][{} {} {}]", |
| 123 | entry.seq, entry.core_id, printer_core, |
| 124 | kLevelLabel[static_cast<uint8_t>(entry.level)]); |
| 125 | *hdr_end = '\0'; |
| 126 | PutStr(kLevelColor[static_cast<uint8_t>(entry.level)]); |
| 127 | PutStr(hdr_buf); |
| 128 | PutStr(entry.msg); |
| 129 | PutStr(kReset); |
| 130 | PutStr("\n"); |
| 131 | } |
| 132 | |
| 133 | drain_flag.clear(std::memory_order_release); |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * @brief 核心实现:格式化消息并入队,随后尝试排空 |
no test coverage detected