diff --git a/doc/整体架构思路.md b/doc/整体架构思路.md index e7fb868..1730009 100644 --- a/doc/整体架构思路.md +++ b/doc/整体架构思路.md @@ -278,7 +278,7 @@ WaterFallRingBuffer ringBuffer TimeAxis::mRingBuffer SweepFrequent::mFrequents Planisphere::dataList -Afterglow cachedPowerData / oldCachePowerData / mutexPowerData +Afterglow cachedPowerData / oldCachePowerData / mergedPowerData Spectrum curPowers / maxPowers / minPowers / frequents ``` @@ -385,13 +385,11 @@ Input dirty 不递增 edit_state.version。 prepareData 的标准流程: ```text -lock mBufferLock syncStatePipeline() 读取 render_state 配置 读取 render_input 增量 更新 RenderCache clearRenderInput() -unlock mBufferLock ``` syncStatePipeline 内部同时处理: @@ -401,6 +399,14 @@ State edit -> ready -> render Input edit -> ready -> render ``` +prepareData 不再持有 RenderData 对象级锁。 + +edit_state 写入必须通过 State_Edit lease。 + +edit_input 写入必须通过 Input_Edit lease。 + +RenderCache 只允许 render 流程内部更新。 + prepareData 不应该写 Color。 prepareData 不应该触发 QWidget 绘制。 @@ -453,7 +459,72 @@ draw 不做输入队列交换。 把配置项放 InputData。 ``` -## 12. 最终规则 +## 12. 锁使用边界 + +radio 渲染链路不允许使用 RenderData 对象级大锁。 + +允许存在的同步只有下面几类: + +```text +Triple_Role_Buffer_Control: + 使用 atomic busy / slot_state / wait / notify。 + 只保护物理 buffer lease 和 role 交换。 + +RenderPipeline: + 使用 color buffer version / paintRequestPending / editStateVersion。 + 只保护帧发布和 Qt update 请求合并。 + +Plot / TimerThread: + mRenderEnabled / mDestroying / mActiveRenderTasks / pending render size 使用 atomic。 + mRenderTaskMutex + mRenderTaskDone 只用于 Plot 析构等待已投递任务结束。 + TimerThread::postAndWait 的局部 mutex + condition_variable 只用于跨线程同步 shutdown/removePlot。 + +PerformanceShower: + mMutex 只保护统计 map 和显示列表。 +``` + +不允许重新引入: + +```text +RenderData::mBufferLock +prepareData 全局锁 +render size mutex +Graphic resize mutex +HoverInfo 独立 mutex +PrePareMutiDataMutex +SpinLock / SpinLockGuard +Singleton mutex + atomic 双重检查 +``` + +prepareData 和 draw 的并发边界由调度流保证: + +```text +submitRender 进入 asio scheduler。 +scheduler 串行推进 jobState。 +prepareData 在 scheduler 阶段消费 State/Input。 +renderColor 在 CPU 阶段只读取 State_Render 和 RenderCache。 +finishRender 回到 scheduler 发布 Color。 +``` + +CPP_Core 和第三方库内部同步不属于 radio 渲染架构边界: + +```text +RingBuffer_MT / StreamRingBuffer_MT: + 通用多线程容器版本。 + +SM_RingBuffer / Cross_Process_Mutex: + 跨进程共享内存同步。 + +Frequency_Limit: + 通用频率限制器。 + +spdlog / asio / googlepinyin: + 第三方或通用库内部同步。 +``` + +这些同步不能向 RenderData、prepareData、draw 路径扩散。 + +## 13. 最终规则 ```text State 负责配置快照。 diff --git a/module/radio/BackEnd/BackEnd.h b/module/radio/BackEnd/BackEnd.h index d88bc23..51d3013 100644 --- a/module/radio/BackEnd/BackEnd.h +++ b/module/radio/BackEnd/BackEnd.h @@ -2,7 +2,6 @@ #define BackEnd_H #include -#include #include #include diff --git a/module/radio/Global.h b/module/radio/Global.h index 5f70609..219a858 100644 --- a/module/radio/Global.h +++ b/module/radio/Global.h @@ -14,62 +14,7 @@ #include #include #include - #include "psc_global_include/Singleton.hpp" - -// template -// class Singleton { -// public: -// static Derived* instance() { -// Derived* temp = instance_.load(std::memory_order_acquire); -// if (temp == nullptr) { -// std::lock_guard lock(mutex_); -// temp = instance_.load(std::memory_order_relaxed); -// if (temp == nullptr) { -// temp = new Derived; -// instance_.store(temp, std::memory_order_release); -// } -// } -// return temp; -// } -// Singleton(const Singleton&) = delete; -// Singleton& operator=(const Singleton&) = delete; -// protected: -// Singleton() = default; -// ~Singleton() = default; -// private: -// static std::atomic instance_; -// static std::mutex mutex_; -// }; -// template -// std::atomic Singleton::instance_(nullptr); -// template -// std::mutex Singleton::mutex_; - -//template -//class Singleton { -//public: -// static T *instance() { -// if(!mInstance) { -// mInstance = new T(); -// } -// return mInstance; -// } -// virtual ~Singleton() = default; -// Singleton(T &&) = delete; -// Singleton(const T &) = delete; -// void operator=(const T &) = delete; -//protected: -// Singleton() = default; -// static T* mInstance; -//}; -//template T* Singleton::mInstance = nullptr; - - - - - - class Global : public Psc::Singleton { public: explicit Global(); @@ -101,4 +46,4 @@ QPushButton *createClickButton(const QString &text, int fontSize, const std::fun QPushButton* createNormal(const QString& text, int fontSize, const std::function& mFunc = nullptr); -#endif \ No newline at end of file +#endif diff --git a/module/radio/Toolbox_private/Singleton.hpp b/module/radio/Toolbox_private/Singleton.hpp index ab913fa..1e0247f 100644 --- a/module/radio/Toolbox_private/Singleton.hpp +++ b/module/radio/Toolbox_private/Singleton.hpp @@ -1,34 +1,18 @@ #ifndef Toolbox_Singleton_H #define Toolbox_Singleton_H -#include namespace Toolbox { template class Singleton { public: static Derived *instance() { - Derived *temp = instance_.load(std::memory_order_acquire); - if (temp == nullptr) { - std::lock_guard lock(mutex_); - temp = instance_.load(std::memory_order_relaxed); - if (temp == nullptr) { - temp = new Derived; - instance_.store(temp, std::memory_order_release); - } - } - return temp; + static Derived instance; + return &instance; } Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete; protected: Singleton() = default; ~Singleton() = default; - private: - static std::atomic instance_; - static std::mutex mutex_; }; - template - std::atomic Singleton::instance_(nullptr); - template - std::mutex Singleton::mutex_; } -#endif \ No newline at end of file +#endif diff --git a/module/radio/Toolbox_private/SpinLock.cpp b/module/radio/Toolbox_private/SpinLock.cpp deleted file mode 100644 index 2280382..0000000 --- a/module/radio/Toolbox_private/SpinLock.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include "SpinLock.h" -namespace Toolbox { - void SpinLock::lock() { - while (flag.test_and_set(std::memory_order_acquire)) {} - } - bool SpinLock::tryLock() { - return !flag.test_and_set(std::memory_order_acquire); - } - bool SpinLock::tryLock(int durationMillis) { - if (durationMillis == 0) { - return tryLock(); - } - auto duration = std::chrono::milliseconds(durationMillis); - auto start = std::chrono::steady_clock::now(); - while (std::chrono::steady_clock::now() - start < duration) { - if (tryLock()) { - return true; - } - } - return false; - } - void SpinLock::unlock() { - flag.clear(std::memory_order_release); - } - SpinLockGuard::~SpinLockGuard() { - if (mLock) mLock->unlock(); - } - SpinLockGuard::SpinLockGuard(SpinLock *lock) : mLock(lock) { - if (mLock) mLock->lock(); - } -} diff --git a/module/radio/Toolbox_private/SpinLock.h b/module/radio/Toolbox_private/SpinLock.h deleted file mode 100644 index ac80eb3..0000000 --- a/module/radio/Toolbox_private/SpinLock.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef Toolbox_SpinLock_H -#define Toolbox_SpinLock_H -#include -namespace Toolbox { - class SpinLock { - public: - void lock(); - bool tryLock(); - bool tryLock(int durationMillis); - void unlock(); - private: - std::atomic_flag flag = ATOMIC_FLAG_INIT; - }; - class SpinLockGuard { - public: - explicit SpinLockGuard(SpinLock *lock); - ~SpinLockGuard(); - private: - SpinLock *mLock; - }; -} -#endif \ No newline at end of file diff --git a/module/radio/Toolbox_private/export.h b/module/radio/Toolbox_private/export.h index 119f9d2..f6cf054 100644 --- a/module/radio/Toolbox_private/export.h +++ b/module/radio/Toolbox_private/export.h @@ -1,8 +1,7 @@ #include "Node.hpp" #include "CircularLinkedList.hpp" -#include "SpinLock.h" #include "Singleton.hpp" #include "RollObject.h" #include "SingletonWidget.hpp" #include "view/FileFolderBar.h" -#include "pinyin/VirtualKeyBoard.h" \ No newline at end of file +#include "pinyin/VirtualKeyBoard.h"