From e8a27bb203fe2aff70390a5eca002d7438da9b0f Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期三, 22 十月 2025 14:24:34 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang

---
 SourceCode/Bond/DAQBridge/buffer/SampleBuffer.cpp |  116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/SourceCode/Bond/DAQBridge/buffer/SampleBuffer.cpp b/SourceCode/Bond/DAQBridge/buffer/SampleBuffer.cpp
new file mode 100644
index 0000000..be7145e
--- /dev/null
+++ b/SourceCode/Bond/DAQBridge/buffer/SampleBuffer.cpp
@@ -0,0 +1,116 @@
+// SampleBuffer.cpp
+#include "SampleBuffer.h"
+#include <algorithm>
+
+void SampleBuffer::push(int64_t ts_ms, double v) {
+    std::unique_lock lk(mtx_);
+    if (!data_.empty() && ts_ms < data_.back().ts_ms) {
+        ts_ms = data_.back().ts_ms; // 简单纠正为非递减;严格场景可改为丢弃/插入排序
+    }
+    data_.push_back({ ts_ms, v });
+    pruneUnlocked(ts_ms); // 用当前写入时间作为参考时间
+}
+
+std::vector<Sample> SampleBuffer::getSince(int64_t tsExclusive, size_t maxCount) const {
+    std::shared_lock lk(mtx_);
+    std::vector<Sample> out;
+    if (data_.empty()) return out;
+    const size_t start = lowerBoundIndex(tsExclusive);
+    if (start >= data_.size()) return out;
+    const size_t n = std::min(maxCount, data_.size() - start);
+    out.reserve(n);
+    for (size_t i = 0; i < n; ++i) out.push_back(data_[start + i]);
+    return out;
+}
+
+std::vector<Sample> SampleBuffer::getRange(int64_t from_ts, int64_t to_ts, size_t maxCount) const {
+    if (to_ts < from_ts) return {};
+    std::shared_lock lk(mtx_);
+    std::vector<Sample> out;
+    if (data_.empty()) return out;
+    const size_t L = lowerBoundInclusive(from_ts);
+    const size_t R = upperBoundInclusive(to_ts);
+    if (L >= R) return out;
+    const size_t n = std::min(maxCount, R - L);
+    out.reserve(n);
+    for (size_t i = 0; i < n; ++i) out.push_back(data_[L + i]);
+    return out;
+}
+
+size_t SampleBuffer::size() const { std::shared_lock lk(mtx_); return data_.size(); }
+bool   SampleBuffer::empty() const { std::shared_lock lk(mtx_); return data_.empty(); }
+int64_t SampleBuffer::latestTs() const {
+    std::shared_lock lk(mtx_);
+    return data_.empty() ? 0 : data_.back().ts_ms;
+}
+void SampleBuffer::clear() {
+    std::unique_lock lk(mtx_);
+    data_.clear();
+}
+
+void SampleBuffer::setPolicy(const RetentionPolicy& p) {
+    std::unique_lock lk(mtx_);
+    policy_ = p;
+    // 立即按新策略清一次(以“当前最新 ts”为参考)
+    pruneUnlocked(data_.empty() ? 0 : data_.back().ts_ms);
+}
+RetentionPolicy SampleBuffer::getPolicy() const {
+    std::shared_lock lk(mtx_);
+    return policy_;
+}
+
+void SampleBuffer::pruneUnlocked(int64_t ref_now_ms) {
+    switch (policy_.mode) {
+    case RetainMode::ByCount:
+        if (policy_.maxSamples > 0) {
+            while (data_.size() > policy_.maxSamples) data_.pop_front();
+        }
+        break;
+    case RetainMode::ByRollingAge: {
+        if (policy_.maxAge.count() > 0) {
+            const int64_t cutoff = ref_now_ms - policy_.maxAge.count();
+            while (!data_.empty() && data_.front().ts_ms < cutoff) data_.pop_front();
+        }
+        break;
+    }
+    case RetainMode::ByAbsoluteRange: {
+        const bool valid = (policy_.absTo >= policy_.absFrom);
+        if (valid) {
+            // 丢弃窗口之外的数据(两端都裁)
+            while (!data_.empty() && data_.front().ts_ms < policy_.absFrom) data_.pop_front();
+            while (!data_.empty() && data_.back().ts_ms > policy_.absTo)   data_.pop_back();
+        }
+        break;
+    }
+    }
+}
+
+size_t SampleBuffer::lowerBoundIndex(int64_t tsExclusive) const {
+    size_t L = 0, R = data_.size();
+    while (L < R) {
+        size_t m = (L + R) >> 1;
+        if (data_[m].ts_ms <= tsExclusive) L = m + 1; else R = m;
+    }
+    return L; // 第一个 > tsExclusive
+}
+size_t SampleBuffer::lowerBoundInclusive(int64_t tsInclusive) const {
+    size_t L = 0, R = data_.size();
+    while (L < R) {
+        size_t m = (L + R) >> 1;
+        if (data_[m].ts_ms < tsInclusive) L = m + 1; else R = m;
+    }
+    return L; // 第一个 >= tsInclusive
+}
+size_t SampleBuffer::upperBoundInclusive(int64_t tsInclusive) const {
+    size_t L = 0, R = data_.size();
+    while (L < R) {
+        size_t m = (L + R) >> 1;
+        if (data_[m].ts_ms <= tsInclusive) L = m + 1; else R = m;
+    }
+    return L; // 最后一个 <= tsInclusive 的下一个位置
+}
+
+int64_t SampleBuffer::earliestTs() const {
+    std::shared_lock lk(mtx_);
+    return data_.empty() ? 0 : data_.front().ts_ms;
+}
\ No newline at end of file

--
Gitblit v1.9.3