From ad9693dfba9608e7780539ac5c0e2f42c7a8b5a9 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Thu, 23 Jul 2026 12:27:06 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YSGraphic_Core/Axis/AbsAxis_p.h | 1 - YSGraphic_Core/Axis/Axis_p.h | 17 ++--- YSGraphic_Core/Axis/FrequentAxis_p.h | 4 -- YSGraphic_Core/Axis/TimeAxis.cpp | 6 +- YSGraphic_Core/Axis/TimeAxis_p.h | 7 +- YSGraphic_Core/CacheModel.h | 1 - YSGraphic_Core/GlobalTypes.h | 21 +----- YSGraphic_Core/RenderAble.cpp | 51 +++++---------- YSGraphic_Core/RenderAble.h | 34 ++++++---- YSGraphic_Core/base/Global.cpp | 9 +-- YSGraphic_Core/base/Graphic.cpp | 11 ++-- YSGraphic_Core/base/Graphic.h | 2 - YSGraphic_Core/base/MutiSelectRect_p.h | 20 +++--- YSGraphic_Core/base/PerformanceShower.cpp | 18 ++++- YSGraphic_Core/base/PerformanceShower_p.h | 6 +- YSGraphic_Core/base/Plot.cpp | 76 +++++++++++----------- YSGraphic_Core/base/Plot.h | 38 ----------- YSGraphic_Core/base/Plot_p.h | 5 +- YSGraphic_Core/base/Spin_Lock.h | 7 -- YSGraphic_Core/base/export.h | 1 - YSGraphic_Core/plottable/Afterglow.cpp | 36 +++++----- YSGraphic_Core/plottable/Afterglow_p.h | 17 ++--- YSGraphic_Core/plottable/AudioFrequent_p.h | 7 +- YSGraphic_Core/plottable/HoverInfo.h | 64 +++++++++--------- YSGraphic_Core/plottable/Planisphere_p.h | 1 - YSGraphic_Core/plottable/Spectrum.cpp | 19 +++--- YSGraphic_Core/plottable/Spectrum_p.h | 7 +- YSGraphic_Core/plottable/SweepFrequent.cpp | 15 +++-- YSGraphic_Core/plottable/SweepFrequent_p.h | 1 - YSGraphic_Core/plottable/WaterFall_p.h | 13 ++-- 30 files changed, 222 insertions(+), 293 deletions(-) delete mode 100644 YSGraphic_Core/base/Spin_Lock.h diff --git a/YSGraphic_Core/Axis/AbsAxis_p.h b/YSGraphic_Core/Axis/AbsAxis_p.h index c17233f..e565ca5 100644 --- a/YSGraphic_Core/Axis/AbsAxis_p.h +++ b/YSGraphic_Core/Axis/AbsAxis_p.h @@ -26,7 +26,6 @@ namespace YSG { void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); } diff --git a/YSGraphic_Core/Axis/Axis_p.h b/YSGraphic_Core/Axis/Axis_p.h index f556c85..ba96d73 100644 --- a/YSGraphic_Core/Axis/Axis_p.h +++ b/YSGraphic_Core/Axis/Axis_p.h @@ -21,12 +21,12 @@ namespace YSG { bool selectTest(const QPointF& pos) override {return true;} void wheelEvent(QWheelEvent* event) override { if(useWheel) { - SpinLockGuard _guard(&mBufferLock); - RenderEditGuard _editGuard(this); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + auto rc = reinterpret_cast(stateByIndex(lease.index)); + RenderEditGuard _editGuard(this, lease); const double delta = event->angleDelta().y(); double wheelSteps = delta / 120.0; double factor = std::pow(0.8, wheelSteps); - auto rc = editState(); double cursor_coord = pixelToCoord(event->position().x(), SRC::Edit); double new_coordLength = rc->coordLength * factor; double new_coordStart = cursor_coord - new_coordLength * (cursor_coord - rc->coordStart) / rc->coordLength; @@ -42,22 +42,23 @@ namespace YSG { if(!useDrag) return; if(event->button() != Qt::LeftButton) return; if(dragging) return; - SpinLockGuard _guard(&mBufferLock); dragging = true; startGlobalPos = QCursor::pos(); startPos = event->pos(); - auto rc = editState(); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + auto rc = reinterpret_cast(stateByIndex(lease.index)); startCoordValue = rc->coordStart; pixelPreCoord = rc->coordLength/static_cast(rc->pixelSize); + mStateControl.unmark_use(lease); } void mouseMoveEvent(QMouseEvent* event) override { if(!useDrag) return; if(!(event->buttons() & Qt::LeftButton)) return; if(!dragging) return; - SpinLockGuard _guard(&mBufferLock); - RenderEditGuard _editGuard(this); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + auto rc = reinterpret_cast(stateByIndex(lease.index)); + RenderEditGuard _editGuard(this, lease); QPoint delt = startGlobalPos - QCursor::pos(); - auto rc = editState(); auto coordDelt = pixelPreCoord * (rc->orientation == Qt::Horizontal ? delt.x() :delt.y()); rc->coordStart = startCoordValue + coordDelt; } diff --git a/YSGraphic_Core/Axis/FrequentAxis_p.h b/YSGraphic_Core/Axis/FrequentAxis_p.h index d73fa93..c3fbc48 100644 --- a/YSGraphic_Core/Axis/FrequentAxis_p.h +++ b/YSGraphic_Core/Axis/FrequentAxis_p.h @@ -40,10 +40,6 @@ namespace YSG { } if (beforeUnitType != xUnitType) { renderState()->unitText = "频率/" + getXUnitTypeString(xUnitType); - { - SpinLockGuard _guard (&mBufferLock); - editState()->unitText = "频率/" + getXUnitTypeString(xUnitType); - } } } QVector result; diff --git a/YSGraphic_Core/Axis/TimeAxis.cpp b/YSGraphic_Core/Axis/TimeAxis.cpp index 51cd556..1825930 100644 --- a/YSGraphic_Core/Axis/TimeAxis.cpp +++ b/YSGraphic_Core/Axis/TimeAxis.cpp @@ -10,10 +10,10 @@ namespace YSG { int TimeAxis::giveData(QTime time) { if(!ok()) return -1; TimeAxisPrivate* pd = d(); - SpinLockGuard _guard(&pd->mBufferLock); - RenderInputGuard _inputGuard(pd); + Triple_Buffer_Lease inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit); + RenderInputGuard _inputGuard(pd, inputLease); std::pair ret = pd->mTimeTicker.getNewDataTickInfo(); - auto input = reinterpret_cast(pd->inputData(Input_Edit)); + auto input = reinterpret_cast(pd->inputDataByIndex(inputLease.index)); input->mAllTime.push_back(time); if(ret.second) { input->mData.push_front({time, ret.first}); diff --git a/YSGraphic_Core/Axis/TimeAxis_p.h b/YSGraphic_Core/Axis/TimeAxis_p.h index 065a66f..28aa9a3 100644 --- a/YSGraphic_Core/Axis/TimeAxis_p.h +++ b/YSGraphic_Core/Axis/TimeAxis_p.h @@ -95,11 +95,12 @@ namespace YSG { YSG::RingBuffer mRingBuffer; std::list mData; void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); auto d = renderInputData(); auto s = renderState(); - auto sc = editState(); + Triple_Buffer_Lease inputLease = mInputControl.wait_mark_use_role(Input_Edit); + Triple_Buffer_Lease stateLease = mStateControl.wait_mark_use_role(State_Edit); + auto sc = reinterpret_cast(stateByIndex(stateLease.index)); bool refreshSpace = false; if(mTimeTicker.mTimePointSize != s->timePointSize) { mTimeTicker.setTimePointSize(s->timePointSize); @@ -164,6 +165,8 @@ namespace YSG { labels.append(t.mTime.toString(s->timeFormat)); ++i; } + mStateControl.unmark_use(stateLease); + mInputControl.unmark_use(inputLease); } diff --git a/YSGraphic_Core/CacheModel.h b/YSGraphic_Core/CacheModel.h index e8aedc4..0bd8c0b 100644 --- a/YSGraphic_Core/CacheModel.h +++ b/YSGraphic_Core/CacheModel.h @@ -5,7 +5,6 @@ namespace YSG{ struct CacheModel { std::array buffers; Triple_Role_Buffer_Control control; - SpinLock mLock; void syncStatePipeline() { auto lease = control.wait_mark_use_role(State_Ready); buffers[lease.index] = *state(SRC::Edit); diff --git a/YSGraphic_Core/GlobalTypes.h b/YSGraphic_Core/GlobalTypes.h index fef36cb..ab6c585 100644 --- a/YSGraphic_Core/GlobalTypes.h +++ b/YSGraphic_Core/GlobalTypes.h @@ -76,22 +76,6 @@ namespace YSG { }; QDebug operator<<(QDebug debug, const Range &range); - struct LIB_DECL SpinLock { - void lock(); - bool tryLock(); - bool tryLock(int durationMillis); - void unlock(); - private: - std::atomic_flag flag = ATOMIC_FLAG_INIT; - }; - - struct LIB_DECL SpinLockGuard { - explicit SpinLockGuard(SpinLock *lock); - ~SpinLockGuard(); - SpinLock *mLock; - }; - - enum class LIB_DECL SRC : std::uint8_t { Edit, Ready, @@ -191,8 +175,9 @@ Type name(SRC src = SRC::Edit); public: \ void set_##name(Type name) { \ className##Private* pd = d(); \ - className##RenderState* sc = reinterpret_cast(pd->state(State_Edit)); \ - SpinLockGuard _guard(&pd->mBufferLock); \ + Triple_Buffer_Lease _stateLease = pd->mStateControl.wait_mark_use_role(State_Edit); \ + className##RenderState* sc = reinterpret_cast(pd->stateByIndex(_stateLease.index)); \ + RenderEditGuard _editGuard(pd, _stateLease); \ sc->##name = name; \ } \ Type name(SRC src) { \ diff --git a/YSGraphic_Core/RenderAble.cpp b/YSGraphic_Core/RenderAble.cpp index ec71c25..4586a1d 100644 --- a/YSGraphic_Core/RenderAble.cpp +++ b/YSGraphic_Core/RenderAble.cpp @@ -16,34 +16,6 @@ namespace YSG { return debug; } - 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(); - } RenderAble::RenderPipeline::RenderPipeline() { colorControl.reset(); } @@ -96,18 +68,23 @@ namespace YSG { paintRequestPending.store(false, std::memory_order_release); return tryFrontColor(); } - RenderEditGuard::RenderEditGuard(RenderData* data) : mData(data) { + RenderEditGuard::RenderEditGuard(RenderData* data, Triple_Buffer_Lease lease) : mData(data), mLease(lease) { } RenderEditGuard::~RenderEditGuard() { - if(mData && mData->qPtr) mData->qPtr->markStateDirty(); + if(!mData) return; + ++mData->stateByIndex(mLease.index)->version; + if(mData->qPtr) mData->qPtr->markRenderDirty(); + mData->unmarkState(mLease); } - RenderInputGuard::RenderInputGuard(RenderData* data) : mData(data) { + RenderInputGuard::RenderInputGuard(RenderData* data, Triple_Buffer_Lease lease) : mData(data), mLease(lease) { } RenderInputGuard::~RenderInputGuard() { - if(mData) mData->markInputDirty(); + if(!mData) return; + mData->markInputDirty(mLease); + mData->mInputControl.unmark_use(mLease); } - void RenderData::markInputDirty() { - InputBufferSlot& slot = inputSlot(Input_Edit); + void RenderData::markInputDirty(Triple_Buffer_Lease lease) { + InputBufferSlot& slot = inputSlotByIndex(lease.index); slot.version = ++mInputVersion; slot.pending = true; if(qPtr) qPtr->markRenderDirty(); @@ -135,7 +112,11 @@ namespace YSG { if(mPlot) mPlot->markRenderStateDirty(); } void RenderAble::markStateDirty() { - if(dPtr) ++dPtr->state(State_Edit)->version; + if(dPtr) { + auto lease = dPtr->mStateControl.wait_mark_use_role(State_Edit); + ++dPtr->stateByIndex(lease.index)->version; + dPtr->mStateControl.unmark_use(lease); + } markRenderDirty(); } void RenderAble::markRenderDirty() { diff --git a/YSGraphic_Core/RenderAble.h b/YSGraphic_Core/RenderAble.h index 3e09f89..d1594c7 100644 --- a/YSGraphic_Core/RenderAble.h +++ b/YSGraphic_Core/RenderAble.h @@ -266,7 +266,6 @@ struct InputBufferSlot { bool pending = false; }; struct RenderData { - SpinLock mBufferLock; RenderAble* qPtr{}; bool mRenderStart = false; Triple_Role_Buffer_Control mStateControl; @@ -314,7 +313,7 @@ struct RenderData { const InputBufferSlot& inputSlotByIndex(std::uint8_t index) const { return mInputBuffers[index]; } - void markInputDirty(); + void markInputDirty(Triple_Buffer_Lease lease); void clearInputRole(std::uint8_t role) { InputBufferSlot& slot = inputSlot(role); slot.data->clear(); @@ -346,7 +345,6 @@ protected: } virtual void draw(QPainter* painter) {} virtual void prepareData() { - SpinLockGuard g(&mBufferLock); syncStatePipeline(); } virtual bool selectTest(const QPointF& pos) { @@ -384,14 +382,16 @@ struct BaseRenderData : RenderData { }; class Plot; struct LIB_DECL RenderEditGuard { - explicit RenderEditGuard(RenderData* data); + RenderEditGuard(RenderData* data, Triple_Buffer_Lease lease); ~RenderEditGuard(); RenderData* mData{}; + Triple_Buffer_Lease mLease{}; }; struct LIB_DECL RenderInputGuard { - explicit RenderInputGuard(RenderData* data); + RenderInputGuard(RenderData* data, Triple_Buffer_Lease lease); ~RenderInputGuard(); RenderData* mData{}; + Triple_Buffer_Lease mLease{}; }; struct RenderAble { enum class JobState { @@ -533,11 +533,13 @@ private: ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ + Triple_Buffer_Lease editLease = mStateControl.wait_mark_use_role(State_Edit); \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ - auto edit = editState(); \ + auto edit = reinterpret_cast(stateByIndex(editLease.index)); \ if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ + mStateControl.unmark_use(editLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ @@ -564,11 +566,13 @@ private: ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ + Triple_Buffer_Lease editLease = mStateControl.wait_mark_use_role(State_Edit); \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ - auto edit = editState(); \ + auto edit = reinterpret_cast(stateByIndex(editLease.index)); \ if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ + mStateControl.unmark_use(editLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ @@ -595,11 +599,13 @@ private: ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ + Triple_Buffer_Lease editLease = mStateControl.wait_mark_use_role(State_Edit); \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ - auto edit = editState(); \ + auto edit = reinterpret_cast(stateByIndex(editLease.index)); \ if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ + mStateControl.unmark_use(editLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ @@ -618,11 +624,11 @@ private: if(!mRenderStart) mRenderStart = true; \ } #define INIT_SET(className) className##Private* pd = d(); \ - className##RenderState* sc = reinterpret_cast(pd->state(State_Edit));\ - SpinLockGuard _guard(&pd->mBufferLock); \ - RenderEditGuard _editGuard(pd); + Triple_Buffer_Lease _stateLease = pd->mStateControl.wait_mark_use_role(State_Edit); \ + className##RenderState* sc = reinterpret_cast(pd->stateByIndex(_stateLease.index));\ + RenderEditGuard _editGuard(pd, _stateLease); #define INIT_INPUT(className) className##Private* pd = d(); \ - className##InputData* input = reinterpret_cast(pd->inputData(Input_Edit)); \ - SpinLockGuard _guard(&pd->mBufferLock); \ - RenderInputGuard _inputGuard(pd); + Triple_Buffer_Lease _inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit); \ + className##InputData* input = reinterpret_cast(pd->inputDataByIndex(_inputLease.index)); \ + RenderInputGuard _inputGuard(pd, _inputLease); } diff --git a/YSGraphic_Core/base/Global.cpp b/YSGraphic_Core/base/Global.cpp index 69afc68..112ea37 100644 --- a/YSGraphic_Core/base/Global.cpp +++ b/YSGraphic_Core/base/Global.cpp @@ -37,8 +37,9 @@ namespace YSG { for (auto &plot: mPlots) { plot->d->mTimerThread = this; plot->d->mRenderTimer = std::make_unique(d->mIoContext); - if(plot->isVisible()) plot->d->mRenderEnabled = true; - if(plot->d->mRenderEnabled) plot->scheduleRenderTimer(); + plot->d->mRenderSize = QSize(plot->d->mPendingRenderWidth.load(std::memory_order_acquire), plot->d->mPendingRenderHeight.load(std::memory_order_acquire)); + if(plot->isVisible()) plot->d->mRenderEnabled.store(true, std::memory_order_release); + if(plot->d->mRenderEnabled.load(std::memory_order_acquire)) plot->scheduleRenderTimer(); plot->requestRender(); } d->mIoContext.run(); @@ -123,7 +124,7 @@ namespace YSG { void TimerThread::removePlotOnScheduler(Plot* plot) { mPlots.removeAll(plot); PlotPrivate* data = plot->d; - data->mRenderEnabled = false; + data->mRenderEnabled.store(false, std::memory_order_release); if(data->mRenderTimer) { data->mRenderTimer->cancel(); data->mRenderTimer.reset(); @@ -134,7 +135,7 @@ namespace YSG { for(Plot* plot : mPlots) { PlotPrivate* data = plot->d; data->mDestroying.store(true, std::memory_order_release); - data->mRenderEnabled = false; + data->mRenderEnabled.store(false, std::memory_order_release); if(data->mRenderTimer) { data->mRenderTimer->cancel(); data->mRenderTimer.reset(); diff --git a/YSGraphic_Core/base/Graphic.cpp b/YSGraphic_Core/base/Graphic.cpp index 0838e26..ce9681c 100644 --- a/YSGraphic_Core/base/Graphic.cpp +++ b/YSGraphic_Core/base/Graphic.cpp @@ -11,13 +11,10 @@ namespace YSG { switch (event->type()) { case QEvent::Resize: { auto e = reinterpret_cast(event); - { - SpinLockGuard g(&mResizeMtx); - for(PainterLayer* b : mPainterBuffers) { - QSize size = e->size(); - b->mBuffer1 = new QPixmap(size); - b->mBuffer2 = new QPixmap(size); - } + for(PainterLayer* b : mPainterBuffers) { + QSize size = e->size(); + b->mBuffer1 = new QPixmap(size); + b->mBuffer2 = new QPixmap(size); } if(mFirstResize) mFirstResize = false; break; diff --git a/YSGraphic_Core/base/Graphic.h b/YSGraphic_Core/base/Graphic.h index 3f03c91..2b5abc1 100644 --- a/YSGraphic_Core/base/Graphic.h +++ b/YSGraphic_Core/base/Graphic.h @@ -31,7 +31,6 @@ namespace YSG{ QVector mLayers; QVector mPainterBuffers; QVector mOpenglBuffers; - SpinLock mPainterRenderMtx, mResizeMtx; bool mFirstResize; protected: bool event(QEvent*) override; @@ -41,7 +40,6 @@ namespace YSG{ }; void render() { if(mFirstResize) return; - SpinLockGuard g(&mResizeMtx); for(OpenglLayer* b : mOpenglBuffers) { b->draw(); } diff --git a/YSGraphic_Core/base/MutiSelectRect_p.h b/YSGraphic_Core/base/MutiSelectRect_p.h index 681ecfd..3db3e5f 100644 --- a/YSGraphic_Core/base/MutiSelectRect_p.h +++ b/YSGraphic_Core/base/MutiSelectRect_p.h @@ -45,9 +45,9 @@ namespace YSG { // event->buttons():返回一个标志,指示当前按下的所有鼠标按钮。可以在任何鼠标事件中使用,特别是 mouseMoveEvent 中。 void mousePressEvent(QMouseEvent* event) override { if (event->button() != Qt::LeftButton) return; - MutiSelectRectRenderState* sc = editState(); - SpinLockGuard _guard(&mBufferLock); - RenderEditGuard _editGuard(this); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + MutiSelectRectRenderState* sc = reinterpret_cast(stateByIndex(lease.index)); + RenderEditGuard _editGuard(this, lease); QVector &rectList = sc->mRects; if (!(QApplication::keyboardModifiers() & Qt::ControlModifier)) { rectList.clear(); @@ -68,9 +68,9 @@ namespace YSG { void mouseMoveEvent(QMouseEvent* event) override { if(!(event->buttons() & Qt::LeftButton)) return; - MutiSelectRectRenderState* sc = editState(); - SpinLockGuard _guard(&mBufferLock); - RenderEditGuard _editGuard(this); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + MutiSelectRectRenderState* sc = reinterpret_cast(stateByIndex(lease.index)); + RenderEditGuard _editGuard(this, lease); QVector &rectList = sc->mRects; if (rectList.empty()) return; rectList.last().setBottomRight(event->pos()); @@ -83,9 +83,9 @@ namespace YSG { void keyPressEvent(QKeyEvent* event) override { if (event->key() != Qt::Key_Escape || !mActive) return; - MutiSelectRectRenderState* sc = editState(); - SpinLockGuard _guard(&mBufferLock); - RenderEditGuard _editGuard(this); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + MutiSelectRectRenderState* sc = reinterpret_cast(stateByIndex(lease.index)); + RenderEditGuard _editGuard(this, lease); mActive = false; QVector &rectList = sc->mRects; if (rectList.empty()) return; @@ -93,8 +93,6 @@ namespace YSG { } void keyReleaseEvent(QKeyEvent* event) override { - MutiSelectRectRenderState* sc = editState(); - SpinLockGuard _guard(&mBufferLock); } diff --git a/YSGraphic_Core/base/PerformanceShower.cpp b/YSGraphic_Core/base/PerformanceShower.cpp index ce08b72..4c92b59 100644 --- a/YSGraphic_Core/base/PerformanceShower.cpp +++ b/YSGraphic_Core/base/PerformanceShower.cpp @@ -12,6 +12,7 @@ namespace YSG { void PerformanceShower::refreshCounter() { + std::lock_guard lock(mMutex); for(CounterLine& value : mCounter) { value.mCountTimes = 0; value.mTotalStart = std::chrono::system_clock::now(); @@ -19,12 +20,21 @@ namespace YSG { } void PerformanceShower::counterIncrease(const QString& counterName) { + std::lock_guard lock(mMutex); if(!mCounter.contains(counterName)) { mCounter[counterName].mName = counterName; mCounter[counterName].mTotalStart = std::chrono::system_clock::now(); } mCounter[counterName].mCountTimes++; } + void PerformanceShower::setPerformanceLine(const QString& key, const PerformanceLine& line) { + std::lock_guard lock(mMutex); + mInfoMap[key] = line; + } + void PerformanceShower::setInfo(const QString& key, const QString& value) { + std::lock_guard lock(mMutex); + mInfos[key] = value; + } void PerformanceShower::paintEvent(QPaintEvent *event) { QPainter painter(this); @@ -34,7 +44,7 @@ namespace YSG { painter.fillRect(rect(), Qt::white); painter.setFont(mFont); { - SpinLockGuard lock(&mMutex); + std::lock_guard lock(mMutex); QFontMetrics fm(mFont); int n = mAllInfo.size(); for (int i = 0; i < n; i++) { @@ -66,6 +76,7 @@ namespace YSG { } QVector PerformanceShower::all() { + std::lock_guard lock(mMutex); QVector infoList = mFixedInfo; for(PerformanceLine& l: mInfoMap) infoList.append(l.toString()); for(CounterLine& c: mCounter) infoList.append(c.toString()); @@ -76,9 +87,10 @@ namespace YSG { } void PerformanceShower::refresh() { + QVector infoList = all(); { - SpinLockGuard lock(&mMutex); - mAllInfo = all(); + std::lock_guard lock(mMutex); + mAllInfo = infoList; int n = mAllInfo.size(); if (mOldSize != n) { int maxWidth = 0; diff --git a/YSGraphic_Core/base/PerformanceShower_p.h b/YSGraphic_Core/base/PerformanceShower_p.h index fc032c6..28e7788 100644 --- a/YSGraphic_Core/base/PerformanceShower_p.h +++ b/YSGraphic_Core/base/PerformanceShower_p.h @@ -1,6 +1,7 @@ #pragma once #include "../RenderAble.h" +#include namespace YSG { struct PerformanceLine { PerformanceLine() = default; @@ -56,7 +57,7 @@ namespace YSG { Q_INVOKABLE void firstResize(int w, int h); void refresh(); QVector all(); - SpinLock mMutex; + std::mutex mMutex; QMap mInfoMap; QMap mCounter; QVector mFixedInfo; @@ -64,6 +65,8 @@ namespace YSG { void refreshCounter(); void counterIncrease(const QString& counterName); + void setPerformanceLine(const QString& key, const PerformanceLine& line); + void setInfo(const QString& key, const QString& value); protected: void paintEvent(QPaintEvent *event) override; bool mMoving = false; @@ -88,6 +91,7 @@ namespace YSG { ~Cacl() { if(!mPerformanceShower) return; double useTime = std::chrono::duration(std::chrono::system_clock::now() - mStart).count() * 1000; + std::lock_guard lock(mPerformanceShower->mMutex); if(!mPerformanceShower->mInfoMap.contains(mName)) { mPerformanceShower->mInfoMap[mName] = PerformanceLine(mName); } diff --git a/YSGraphic_Core/base/Plot.cpp b/YSGraphic_Core/base/Plot.cpp index 83579fa..e680955 100644 --- a/YSGraphic_Core/base/Plot.cpp +++ b/YSGraphic_Core/base/Plot.cpp @@ -5,21 +5,6 @@ #include namespace YSG { - class PrePareMutiDataMutexGuard { - public: - QVector mLockList; - PrePareMutiDataMutexGuard(RenderAble* renderAble, Plot* plot) { - for(PrePareMutiDataMutex* curLock : plot->mMutiSpinLock) { - if(curLock->mSet.contains(renderAble)) { - mLockList.append(curLock); - } - } - for(PrePareMutiDataMutex* curLock : mLockList) curLock->lock(renderAble); - } - ~PrePareMutiDataMutexGuard() { - for(PrePareMutiDataMutex* curLock : mLockList) curLock->unlock(); - } - }; static void notifyRenderTaskDone(PlotPrivate* data) { if(data->mActiveRenderTasks.fetch_sub(1, std::memory_order_acq_rel) == 1) data->mRenderTaskDone.notify_all(); } @@ -49,8 +34,6 @@ namespace YSG { return d->mShower; } void Plot::set_usePerformanceShower(bool use) { - SpinLockGuard g(&d->mRenderLock); - if(!use) { PerformanceShower* t = d->mShower; d->mShower = nullptr; @@ -64,7 +47,7 @@ namespace YSG { Plot::~Plot() { d->mDestroying.store(true, std::memory_order_release); - d->mRenderEnabled = false; + d->mRenderEnabled.store(false, std::memory_order_release); if(d->mTimerThread) d->mTimerThread->removePlot(this); { std::unique_lock lock(d->mRenderTaskMutex); @@ -76,7 +59,7 @@ namespace YSG { } bool Plot::isRendering() { - return d->mRenderEnabled; + return d->mRenderEnabled.load(std::memory_order_acquire); } void Plot::startRender(int refreshTimesPreSecond) { @@ -86,7 +69,7 @@ namespace YSG { void Plot::startRender() const { if(d->mDestroying.load(std::memory_order_acquire)) return; - d->mRenderEnabled = true; + d->mRenderEnabled.store(true, std::memory_order_release); if(!d->mTimerThread) return; Plot* self = const_cast(this); PlotPrivate* privateData = d; @@ -105,7 +88,7 @@ namespace YSG { } void Plot::pauseRender() const { - d->mRenderEnabled = false; + d->mRenderEnabled.store(false, std::memory_order_release); if(d->mDestroying.load(std::memory_order_acquire)) return; if(!d->mTimerThread) return; Plot* self = const_cast(this); @@ -137,9 +120,18 @@ namespace YSG { submitRender(); } void Plot::submitRender() { + if(d->mTimerThread && d->mTimerThread->isRunning() && !d->mTimerThread->isSchedulerThread()) { + PlotPrivate* privateData = d; + privateData->mActiveRenderTasks.fetch_add(1, std::memory_order_acq_rel); + d->mTimerThread->post([this, privateData]() { + if(!privateData->mDestroying.load(std::memory_order_acquire)) submitRender(); + notifyRenderTaskDone(privateData); + }); + return; + } if(d->mDestroying.load(std::memory_order_acquire)) return; if(mFirstResize) return; - if(!d->mRenderEnabled) return; + if(!d->mRenderEnabled.load(std::memory_order_acquire)) return; QSize renderSize = d->mRenderSize; if(renderSize.width() <= 0 || renderSize.height() <= 0) return; RenderAble::RenderPipeline& pipeline = d->mPipeline; @@ -149,24 +141,21 @@ namespace YSG { pipeline.renderStateVersion = pipeline.editStateVersion.load(std::memory_order_acquire); if(d->mShower) { d->mShower->counterIncrease("渲染帧率"); - d->mShower->mInfos["interval"] = QString("渲染:%1, global:%2").arg(qRound(1000.0 / (double)d->mRefreshTimesPreSecond)).arg(Global::instance()->mInterval); + d->mShower->setInfo("interval", QString("渲染:%1, global:%2").arg(qRound(1000.0 / (double)d->mRefreshTimesPreSecond)).arg(Global::instance()->mInterval)); } { Cacl prepareData("准备数据耗时: %1 avg: %2", d->mShower); - SpinLockGuard prepareDataLock(&d->mPrepareDataLock); for(Layer* layer : mLayerList) { for(RenderAble *cur : layer->mRenderAbles) { //qDebug() << "info: "<< layer->mLayerName << " " << cur->mObjectName; for(auto rely : cur->mBeRelyList) { if(!rely->mPrepared){ - PrePareMutiDataMutexGuard _guard(rely, this); // qDebug() << cur->mObjectName << "rely: " << mObjectName; rely->prepareData(); rely->mPrepared = true; } } if(!cur->mPrepared){ - PrePareMutiDataMutexGuard _guard(cur, this); cur->prepareData(); //qDebug() << cur->mObjectName << " prepareData"; cur->mPrepared = true; @@ -255,7 +244,7 @@ namespace YSG { color->dirtyRegion = QRegion(QRect(QPoint(0, 0), size)); } void Plot::scheduleRenderTimer() { - if(d->mDestroying.load(std::memory_order_acquire) || !d->mRenderTimer || !d->mRenderEnabled) return; + if(d->mDestroying.load(std::memory_order_acquire) || !d->mRenderTimer || !d->mRenderEnabled.load(std::memory_order_acquire)) return; int interval = std::max(1, qRound(1000.0 / (double)d->mRefreshTimesPreSecond)); d->mRenderTimer->expires_after(std::chrono::milliseconds(interval)); PlotPrivate* privateData = d; @@ -304,23 +293,32 @@ namespace YSG { switch (event->type()){ case QEvent::Resize: { auto e = reinterpret_cast(event); - { - SpinLockGuard guard(&d->mRenderLock); - d->mRenderSize = e->size(); - if(mFirstResize) { - for(Layer* layer : mLayerList) { - for(RenderAble* able : layer->mRenderAbles) { - able->firstResizeEvent(e); - } - } - } + QSize renderSize = e->size(); + d->mPendingRenderWidth.store(renderSize.width(), std::memory_order_release); + d->mPendingRenderHeight.store(renderSize.height(), std::memory_order_release); + if(d->mTimerThread && d->mTimerThread->isRunning()) { + PlotPrivate* privateData = d; + privateData->mActiveRenderTasks.fetch_add(1, std::memory_order_acq_rel); + d->mTimerThread->post([privateData, renderSize]() { + if(!privateData->mDestroying.load(std::memory_order_acquire)) privateData->mRenderSize = renderSize; + notifyRenderTaskDone(privateData); + }); + } else { + d->mRenderSize = renderSize; + } + if(mFirstResize) { for(Layer* layer : mLayerList) { for(RenderAble* able : layer->mRenderAbles) { - able->resizeEvent(e); + able->firstResizeEvent(e); } } - if(mFirstResize) mFirstResize = false; } + for(Layer* layer : mLayerList) { + for(RenderAble* able : layer->mRenderAbles) { + able->resizeEvent(e); + } + } + if(mFirstResize) mFirstResize = false; markRenderStateDirty(); break; } diff --git a/YSGraphic_Core/base/Plot.h b/YSGraphic_Core/base/Plot.h index bfb59b8..9542ac8 100644 --- a/YSGraphic_Core/base/Plot.h +++ b/YSGraphic_Core/base/Plot.h @@ -1,47 +1,10 @@ #pragma once - - #include #include "../RenderAble.h" - - - - namespace YSG { void LIB_DECL startAllRenderThread(); class TimerThread; struct PlotPrivate; - // 此锁用于锁住从mSet里第一个元素,到最后一个元素的渲染过程 用于时间同步 - // mSet 里的元素修改前 加上此锁,可保证 所有的这个元素组数据同步 - class LIB_DECL PrePareMutiDataMutex { - public: - SpinLock mRangeLock; - QSet mSet; - QVector mList; - // lock,unlock都只在Plot渲染函数render里调用 一个线程,所以不用加锁 - std::chrono::system_clock::time_point start; - void lock(RenderAble* a) { - if(mList.empty()) { - mRangeLock.lock(); - start = std::chrono::system_clock::now(); - //qDebug() << "lock " << QTime::currentTime().toString("ss:zzz"); - mList.reserve(mSet.size()); - for(RenderAble* that : mSet) { - mList.append(that); - } - } - mList.removeOne(a); - } - void unlock() { - if(mList.empty()) { - //qDebug() << "unlock " << QTime::currentTime().toString("ss:zzz"); - mRangeLock.unlock(); - double duration = std::chrono::duration(std::chrono::system_clock::now() - start).count() * 1000; - //qDebug() << "duration == " << duration; - } - } - }; - class PerformanceShower; class LIB_DECL Plot : public QWidget { Q_OBJECT @@ -83,7 +46,6 @@ namespace YSG { void startRender(int refreshTimesPreSecond); void startRender() const; void pauseRender() const; - QVector mMutiSpinLock; Plot(); ~Plot() override; PlotPrivate *d{}; diff --git a/YSGraphic_Core/base/Plot_p.h b/YSGraphic_Core/base/Plot_p.h index c5dde08..e61e071 100644 --- a/YSGraphic_Core/base/Plot_p.h +++ b/YSGraphic_Core/base/Plot_p.h @@ -15,14 +15,15 @@ namespace YSG { int mRefreshTimesPreSecond = 30; TimerThread* mTimerThread{}; std::unique_ptr mRenderTimer; - bool mRenderEnabled = false; + std::atomic_bool mRenderEnabled{false}; std::atomic_bool mDestroying{false}; std::atomic_int mActiveRenderTasks{0}; std::condition_variable mRenderTaskDone; std::mutex mRenderTaskMutex; + std::atomic_int mPendingRenderWidth{0}; + std::atomic_int mPendingRenderHeight{0}; QSize mRenderSize; RenderAble::RenderPipeline mPipeline; - SpinLock mBufferLock, mRenderLock, mPrepareDataLock, mMustPrepareDataLock; QColor mBackground = Qt::black; PerformanceShower *mShower{}; }; diff --git a/YSGraphic_Core/base/Spin_Lock.h b/YSGraphic_Core/base/Spin_Lock.h deleted file mode 100644 index f54188e..0000000 --- a/YSGraphic_Core/base/Spin_Lock.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include -#include - -namespace YSG { - -} diff --git a/YSGraphic_Core/base/export.h b/YSGraphic_Core/base/export.h index 12d4492..5f733fc 100644 --- a/YSGraphic_Core/base/export.h +++ b/YSGraphic_Core/base/export.h @@ -4,7 +4,6 @@ #include "RingBuffer.hpp" #include "RollObject.h" #include "SingletonWidget.hpp" -#include "Spin_Lock.h" #include "VirtualKeyBoard/VirtualKeyBoard.h" #include "algorithm.hpp" diff --git a/YSGraphic_Core/plottable/Afterglow.cpp b/YSGraphic_Core/plottable/Afterglow.cpp index dfa7d05..e2ae667 100644 --- a/YSGraphic_Core/plottable/Afterglow.cpp +++ b/YSGraphic_Core/plottable/Afterglow.cpp @@ -14,17 +14,17 @@ namespace YSG { PROP_P(Afterglow, int, initStrongValue) void Afterglow::set_frequentPointSize(int t) { AfterglowPrivate* pd = d(); - AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - SpinLockGuard _guard(&pd->mBufferLock); - RenderEditGuard _editGuard(pd); + Triple_Buffer_Lease lease = pd->mStateControl.wait_mark_use_role(State_Edit); + AfterglowRenderState* sc = reinterpret_cast(pd->stateByIndex(lease.index)); + RenderEditGuard _editGuard(pd, lease); sc->frequentPointSize = std::move(t); sc->bufferSize = sc->frequentPointSize * sc->powerPointSize; } void Afterglow::set_powerPointSize(int t) { AfterglowPrivate* pd = d(); - AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - SpinLockGuard _guard(&pd->mBufferLock); - RenderEditGuard _editGuard(pd); + Triple_Buffer_Lease lease = pd->mStateControl.wait_mark_use_role(State_Edit); + AfterglowRenderState* sc = reinterpret_cast(pd->stateByIndex(lease.index)); + RenderEditGuard _editGuard(pd, lease); sc->powerPointSize = std::move(t); sc->bufferSize = sc->frequentPointSize * sc->powerPointSize; } @@ -43,16 +43,19 @@ namespace YSG { void Afterglow::giveData(const QVector &powerRangeData) { if(!ok()) return; AfterglowPrivate* pd = d(); - SpinLockGuard _guard(&pd->mBufferLock); - AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - if(powerRangeData.size() != sc->frequentPointSize) { + Triple_Buffer_Lease stateLease = pd->mStateControl.wait_mark_use_role(State_Edit); + AfterglowRenderState* sc = reinterpret_cast(pd->stateByIndex(stateLease.index)); + int frequentPointSize = sc->frequentPointSize; + pd->mStateControl.unmark_use(stateLease); + if(powerRangeData.size() != frequentPointSize) { qDebug() << QString("pushData(const QVector &powerRangeData) error 数组大小不匹配 需要%1, 实际为%2") - .arg(sc->frequentPointSize).arg(powerRangeData.size()); + .arg(frequentPointSize).arg(powerRangeData.size()); return; } - auto input = reinterpret_cast(pd->inputData(Input_Edit)); + Triple_Buffer_Lease inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit); + RenderInputGuard _inputGuard(pd, inputLease); + auto input = reinterpret_cast(pd->inputDataByIndex(inputLease.index)); input->mDataList.push_back(powerRangeData); - pd->markInputDirty(); } void AfterglowPrivate::pushData(const QVector& powerRangeData, const AfterglowRenderState* s) { @@ -61,14 +64,11 @@ namespace YSG { double oldRemain = 1.0 - s->attenuationRate; double cacheRemain = s->attenuationRate / (double)s->initStrongValue; for(int i = 0; i < cacheBufferSize; ++i) { - mutexPowerData[i] = oldRemain*oldCachePowerData[i] + cacheRemain*cachedPowerData[i]; + mergedPowerData[i] = oldRemain*oldCachePowerData[i] + cacheRemain*cachedPowerData[i]; cachedPowerData[i] = 0; } - { - SpinLockGuard g(&dataLock); - std::memmove(oldCachePowerData.data(), mutexPowerData.data(), cacheBufferSize * sizeof(double)); - OK.storeRelease(true); - } + std::memmove(oldCachePowerData.data(), mergedPowerData.data(), cacheBufferSize * sizeof(double)); + cacheImageDirty = true; } QVector indexList(s->frequentPointSize); double rate = (double)s->powerPointSize/s->powerRange.size(); diff --git a/YSGraphic_Core/plottable/Afterglow_p.h b/YSGraphic_Core/plottable/Afterglow_p.h index e251a8e..549709f 100644 --- a/YSGraphic_Core/plottable/Afterglow_p.h +++ b/YSGraphic_Core/plottable/Afterglow_p.h @@ -21,15 +21,14 @@ namespace YSG { struct AfterglowPrivate : RenderData { D_Ptr(Afterglow) QImage image; - SpinLock dataLock; - QAtomicInteger OK = false; + bool cacheImageDirty = false; int curIndex = 0; int cacheFrequentPointSize{}; int cachePowerPointSize{}; int cacheBufferSize{}; QVector cachedPowerData; QVector oldCachePowerData; - QVector mutexPowerData; + QVector mergedPowerData; [[nodiscard]] int strengthValue(const AfterglowRenderState* s) const {return (int)((double)s->initStrongValue / (1.0 - s->attenuationRate));} void updateCacheSize(int frequentPointSize, int powerPointSize) { cacheFrequentPointSize = frequentPointSize; @@ -39,8 +38,8 @@ namespace YSG { cachedPowerData.fill(0); oldCachePowerData.resize(cacheBufferSize); oldCachePowerData.fill(0); - mutexPowerData.resize(cacheBufferSize); - mutexPowerData.fill(0); + mergedPowerData.resize(cacheBufferSize); + mergedPowerData.fill(0); curIndex = 0; } void pushData(const QVector& powerRangeData, const AfterglowRenderState* s); @@ -48,8 +47,7 @@ namespace YSG { AfterglowRenderState* s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["colCount, rowCount"] = PerformanceLine(QString("colCount:%1, rowCount:%2") - .arg(s->frequentPointSize).arg( s->powerPointSize)); + shower->setPerformanceLine("colCount, rowCount", PerformanceLine(QString("colCount:%1, rowCount:%2").arg(s->frequentPointSize).arg(s->powerPointSize))); } AbsAxis *hAxis = s->frequentAxis, *vAxis = s->powerAxis, *valueAxis = s->powerAxis; Range &hRange = s->frequentRange, &vRange = s->powerRange; @@ -60,7 +58,7 @@ namespace YSG { image.fill(0); } { - if(OK.loadAcquire() == true) { + if(cacheImageDirty) { QVector& mColorMap = Global::instance()->mColorMap; Cacl c("Afterglow setTime:%1 avg %2", q()->mPlot->d->mShower); //double rate = 1.0/s->strengthValue() * 256.0; @@ -78,7 +76,7 @@ namespace YSG { } //std::cout << std::endl; } - OK.storeRelease(false); + cacheImageDirty = false; } } double x = hAxis->coordToPixel(hRange.lower, SRC::Render); @@ -97,7 +95,6 @@ namespace YSG { } void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); AfterglowRenderState* s = renderState(); if(cacheFrequentPointSize != s->frequentPointSize || cachePowerPointSize != s->powerPointSize) { diff --git a/YSGraphic_Core/plottable/AudioFrequent_p.h b/YSGraphic_Core/plottable/AudioFrequent_p.h index 5df7067..64469aa 100644 --- a/YSGraphic_Core/plottable/AudioFrequent_p.h +++ b/YSGraphic_Core/plottable/AudioFrequent_p.h @@ -22,7 +22,6 @@ namespace YSG { D_Ptr(AudioFrequent) YSG::MutiRingBuffer mMutiBuffer; void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); AudioFrequentRenderState *s = renderState(); AudioFrequentInputData *d = renderInputData(); @@ -30,8 +29,7 @@ namespace YSG { mMutiBuffer.resize({sizeof(double)}, s->timePointSize, s->timePointSize * 10); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["TimePointSize"] = PerformanceLine(QString("timePointSize:%1") - .arg(s->timePointSize)); + shower->setPerformanceLine("TimePointSize", PerformanceLine(QString("timePointSize:%1").arg(s->timePointSize))); } } for(double& power : d->mDataList) { @@ -45,8 +43,7 @@ namespace YSG { AudioFrequentRenderState *s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["timePointSize"] = PerformanceLine(QString("timePointSize:%1") - .arg(s->timeAxis->timePointSize())); + shower->setPerformanceLine("timePointSize", PerformanceLine(QString("timePointSize:%1").arg(s->timeAxis->timePointSize()))); } painter->save(); QPolygonF polyline; diff --git a/YSGraphic_Core/plottable/HoverInfo.h b/YSGraphic_Core/plottable/HoverInfo.h index b88ff68..fdc14c9 100644 --- a/YSGraphic_Core/plottable/HoverInfo.h +++ b/YSGraphic_Core/plottable/HoverInfo.h @@ -37,14 +37,14 @@ namespace YSG { return hoverState(src)->useHoverInfo; } void setUseHoverInfo(bool use) { - SpinLockGuard g(lock()); - hoverState(SRC::Edit)->useHoverInfo = use; - markHoverInfoDirty(); + HoverInfoRenderState* sc = beginHoverEdit(); + sc->useHoverInfo = use; + finishHoverEdit(); } void setHoverInfoFont(const QFont& font) { - SpinLockGuard g(lock()); - hoverState(SRC::Edit)->hoverInfoFont = font; - markHoverInfoDirty(); + HoverInfoRenderState* sc = beginHoverEdit(); + sc->hoverInfoFont = font; + finishHoverEdit(); } QFont HoverInfoFont(SRC src = SRC::Edit) { return hoverState(src)->hoverInfoFont; @@ -53,17 +53,17 @@ namespace YSG { return hoverState(src)->hoverInfoBrush; } void setHoverInfoBackgroundBrush(const QBrush& brush) { - SpinLockGuard g(lock()); - hoverState(SRC::Edit)->hoverInfoBrush = brush.color().isValid() ? brush : Qt::NoBrush; - markHoverInfoDirty(); + HoverInfoRenderState* sc = beginHoverEdit(); + sc->hoverInfoBrush = brush.color().isValid() ? brush : Qt::NoBrush; + finishHoverEdit(); } QPen hoverInfoPen(SRC src = SRC::Edit) { return hoverState(src)->hoverInfoPen; } void setHoverInfoPen(const QPen& pen) { - SpinLockGuard g(lock()); - hoverState(SRC::Edit)->hoverInfoPen = pen.color().isValid() ? pen : Qt::NoPen; - markHoverInfoDirty(); + HoverInfoRenderState* sc = beginHoverEdit(); + sc->hoverInfoPen = pen.color().isValid() ? pen : Qt::NoPen; + finishHoverEdit(); } void getHoverInfoContentsMargins(int& left, int& top, int& right, int& bottom, SRC src) { auto s = hoverState(src); @@ -74,40 +74,37 @@ namespace YSG { } void setHoverInfoContentsMargins(int left, int top, int right, int bottom) { - SpinLockGuard g(lock()); - auto sc = hoverState(SRC::Edit); + HoverInfoRenderState* sc = beginHoverEdit(); sc->hoverInfoLeft = left; sc->hoverInfoTop = top; sc->hoverInfoRight = right; sc->hoverInfoBottom = bottom; - markHoverInfoDirty(); + finishHoverEdit(); } protected: virtual HoverInfoRenderState* hoverState(SRC src) = 0; - virtual SpinLock* lock() = 0; - virtual void markHoverInfoDirty() {} + virtual HoverInfoRenderState* beginHoverEdit() = 0; + virtual void finishHoverEdit() = 0; }; struct LIB_DECL HoverInfoIndependRenderAble : HoverInfoRenderAbleInterFace { private: - SpinLock mtx; HoverInfoRenderState s, sc; - SpinLock* lock() override { - return &mtx; - } HoverInfoRenderState* hoverState(SRC src) override { if(src == SRC::Edit) { return ≻ } return &s; } + HoverInfoRenderState* beginHoverEdit() override { + return ≻ + } + void finishHoverEdit() override { + } public: void drawHover(QPainter* painter, AbsAxis* h, AbsAxis* v) override { s.renderAble = this; sc.renderAble = this; - { - SpinLockGuard g(lock()); - s = sc; - } + s = sc; HoverInfoRenderAbleInterFace::drawHover(painter, h, v); } }; @@ -117,15 +114,22 @@ namespace YSG { That *that() { return static_cast(this); } - SpinLock* lock() override { - return &that()->dPtr->mBufferLock; - } + Triple_Buffer_Lease mHoverLease{}; HoverInfoRenderState* hoverState(SRC src) override { auto t = that(); return dynamic_cast(t->dPtr->state(src)); } - void markHoverInfoDirty() override { - that()->markStateDirty(); + HoverInfoRenderState* beginHoverEdit() override { + auto t = that(); + mHoverLease = t->dPtr->mStateControl.wait_mark_use_role(State_Edit); + return dynamic_cast(t->dPtr->stateByIndex(mHoverLease.index)); + } + void finishHoverEdit() override { + auto t = that(); + ++t->dPtr->stateByIndex(mHoverLease.index)->version; + t->markRenderDirty(); + t->dPtr->mStateControl.unmark_use(mHoverLease); + mHoverLease = {}; } }; } diff --git a/YSGraphic_Core/plottable/Planisphere_p.h b/YSGraphic_Core/plottable/Planisphere_p.h index dfc0ab4..ad60559 100644 --- a/YSGraphic_Core/plottable/Planisphere_p.h +++ b/YSGraphic_Core/plottable/Planisphere_p.h @@ -67,7 +67,6 @@ namespace YSG { void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); PlanisphereInputData *d = renderInputData(); PlanisphereRenderState *s = renderState(); diff --git a/YSGraphic_Core/plottable/Spectrum.cpp b/YSGraphic_Core/plottable/Spectrum.cpp index b94e061..94b7d51 100644 --- a/YSGraphic_Core/plottable/Spectrum.cpp +++ b/YSGraphic_Core/plottable/Spectrum.cpp @@ -127,7 +127,6 @@ namespace YSG { minMarkerValue = curPowers[minIndex]; } double SpectrumPrivate::getY(const double& x, bool& ok) { - SpinLockGuard dd(&mBufferLock); int i = binary_search(x, frequents, ok); if(!ok) return -1; const double& x1 = frequents.at(i); @@ -174,8 +173,7 @@ namespace YSG { auto s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["mFrequentPointSize"] = PerformanceLine(QString("mFrequentPointSize:%1") - .arg(s->frequentPointSize)); + shower->setPerformanceLine("mFrequentPointSize", PerformanceLine(QString("mFrequentPointSize:%1").arg(s->frequentPointSize))); } drawSpectrum(painter, s); if(q()->hoverOK(q())) { @@ -187,15 +185,18 @@ namespace YSG { void Spectrum::giveData(const QVector &lineData){ if(!ok()) return; SpectrumPrivate* pd = d(); - SpinLockGuard _guard(&pd->mBufferLock); - SpectrumRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - if(lineData.size() != sc->frequentPointSize) { - qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << sc->frequentPointSize; + Triple_Buffer_Lease stateLease = pd->mStateControl.wait_mark_use_role(State_Edit); + SpectrumRenderState* sc = reinterpret_cast(pd->stateByIndex(stateLease.index)); + int frequentPointSize = sc->frequentPointSize; + pd->mStateControl.unmark_use(stateLease); + if(lineData.size() != frequentPointSize) { + qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << frequentPointSize; return; } - auto input = reinterpret_cast(pd->inputData(Input_Edit)); + Triple_Buffer_Lease inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit); + RenderInputGuard _inputGuard(pd, inputLease); + auto input = reinterpret_cast(pd->inputDataByIndex(inputLease.index)); input->mDataList.push_back(lineData); - pd->markInputDirty(); } void Spectrum::addCustomMarker(double frequent){ diff --git a/YSGraphic_Core/plottable/Spectrum_p.h b/YSGraphic_Core/plottable/Spectrum_p.h index 0c843ab..594bc91 100644 --- a/YSGraphic_Core/plottable/Spectrum_p.h +++ b/YSGraphic_Core/plottable/Spectrum_p.h @@ -115,7 +115,6 @@ namespace YSG { void drawSpectrum(QPainter* painter, SpectrumRenderState* s); void draw(QPainter* painter) override; void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); auto s = renderState(); if(cacheFrequentPointSize != s->frequentPointSize || cacheFrequentRange != s->frequentRange) { @@ -137,9 +136,9 @@ namespace YSG { return qAbs(power - sc->powerAxis->pixelToCoord(pos.y(), SRC::Render)) < 4; } void setHoverState(const QPoint& pos, bool active) override { - SpinLockGuard guard(&mBufferLock); - RenderEditGuard editGuard(this); - SpectrumRenderState* sc = editState(); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + RenderEditGuard editGuard(this, lease); + SpectrumRenderState* sc = reinterpret_cast(stateByIndex(lease.index)); sc->hoverInfoPos = pos; sc->hoverInfoActive = active; } diff --git a/YSGraphic_Core/plottable/SweepFrequent.cpp b/YSGraphic_Core/plottable/SweepFrequent.cpp index ca63194..926bc97 100644 --- a/YSGraphic_Core/plottable/SweepFrequent.cpp +++ b/YSGraphic_Core/plottable/SweepFrequent.cpp @@ -17,15 +17,18 @@ namespace YSG { void SweepFrequent::giveData(const QVector& data) { if(!ok()) return; SweepFrequentPrivate* pd = d(); - SpinLockGuard _guard(&pd->mBufferLock); - SweepFrequentRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - if(data.size() != sc->blockFrequentPointSize) { - qDebug() << "error data size == " << data.size() << " BlockFrquentPointSize" << sc->blockFrequentPointSize; + Triple_Buffer_Lease stateLease = pd->mStateControl.wait_mark_use_role(State_Edit); + SweepFrequentRenderState* sc = reinterpret_cast(pd->stateByIndex(stateLease.index)); + int blockFrequentPointSize = sc->blockFrequentPointSize; + pd->mStateControl.unmark_use(stateLease); + if(data.size() != blockFrequentPointSize) { + qDebug() << "error data size == " << data.size() << " BlockFrquentPointSize" << blockFrequentPointSize; return; } - auto input = reinterpret_cast(pd->inputData(Input_Edit)); + Triple_Buffer_Lease inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit); + RenderInputGuard _inputGuard(pd, inputLease); + auto input = reinterpret_cast(pd->inputDataByIndex(inputLease.index)); input->mData.push_front(data); - pd->markInputDirty(); } diff --git a/YSGraphic_Core/plottable/SweepFrequent_p.h b/YSGraphic_Core/plottable/SweepFrequent_p.h index 22cbf16..cac6dc1 100644 --- a/YSGraphic_Core/plottable/SweepFrequent_p.h +++ b/YSGraphic_Core/plottable/SweepFrequent_p.h @@ -46,7 +46,6 @@ namespace YSG { } protected: void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); SweepFrequentRenderState *s = renderState(); SweepFrequentInputData *d = renderInputData(); diff --git a/YSGraphic_Core/plottable/WaterFall_p.h b/YSGraphic_Core/plottable/WaterFall_p.h index f3dc28e..136b790 100644 --- a/YSGraphic_Core/plottable/WaterFall_p.h +++ b/YSGraphic_Core/plottable/WaterFall_p.h @@ -81,15 +81,14 @@ namespace YSG { QImage image; bool selectTest(const QPointF& pos) override {return true;} void setHoverState(const QPoint& pos, bool active) override { - SpinLockGuard guard(&mBufferLock); - RenderEditGuard editGuard(this); - WaterFallRenderState* sc = editState(); + Triple_Buffer_Lease lease = mStateControl.wait_mark_use_role(State_Edit); + RenderEditGuard editGuard(this, lease); + WaterFallRenderState* sc = reinterpret_cast(stateByIndex(lease.index)); sc->hoverInfoPos = pos; sc->hoverInfoActive = active; } void prepareData() override { - SpinLockGuard guard(&mBufferLock); syncStatePipeline(); WaterFallInputData* data = renderInputData(); const WaterFallRenderState* s = renderState(); @@ -114,8 +113,7 @@ namespace YSG { WaterFallRenderState* s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["FrequentRectCount"] = PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2") - .arg(s->frequentPointSize).arg(s->timeAxis->timePointSize())); + shower->setPerformanceLine("FrequentRectCount", PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2").arg(s->frequentPointSize).arg(s->timeAxis->timePointSize()))); } AbsAxis *hAxis = s->frequentAxis; TimeAxis *vAxis = s->timeAxis; @@ -131,8 +129,7 @@ namespace YSG { image.fill(q()->mPlot->backgroundColor()); PerformanceShower *shower = q()->mPlot->d->mShower; if(shower) { - shower->mInfoMap["colCount, rowCount"] = PerformanceLine(QString("colCount:%1, rowCount:%2") - .arg(colCount).arg(rowCount)); + shower->setPerformanceLine("colCount, rowCount", PerformanceLine(QString("colCount:%1, rowCount:%2").arg(colCount).arg(rowCount))); } } double valueStartCoord = s->powerRange.lower;