Skip to content

Commit 7ccf62b

Browse files
author
孙羽
committed
Refactor RenderManager and RenderThread to include ticket cancellation and improve thread safety
- Add `CancelAllTickets` method to `RenderThread` to cancel all pending tickets. - Update `RenderManager` destructor to cancel all tickets before stopping threads. - Add checks for `decoder_cache_` in `ClearOldDecoders` and `CreateDecoder`. - Improve thread safety in `StealFromOthers` by unlocking the mutex during `TrySteal`.
1 parent ef404c0 commit 7ccf62b

4 files changed

Lines changed: 49 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
qt6-base-dev qt6-base-dev-tools qt6-base-private-dev qt6-tools-dev qt6-tools-dev-tools \
2828
libavcodec-dev libavformat-dev libavfilter-dev libavutil-dev libswscale-dev libswresample-dev \
2929
libopencolorio-dev libopenimageio-dev libopenexr-dev libexpat1-dev \
30-
portaudio19-dev libgl1-mesa-dev libxkbcommon-dev libgtest-dev openimageio-tools
30+
portaudio19-dev libgl1-mesa-dev libxkbcommon-dev libgtest-dev openimageio-toolsr
3131
3232
- name: Install dependencies (macOS)
3333
if: runner.os == 'macOS'

app/render/rendermanager.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,18 @@ RenderManager::RenderManager(Backend backend, QObject *parent)
104104

105105
RenderManager::~RenderManager()
106106
{
107-
if (gl_thread_) {
108-
// 停止所有渲染线程
109-
for (RenderThread *rt : render_threads_) {
110-
rt->quit();
111-
rt->wait();
112-
}
107+
// 先取消所有待处理的任务
108+
for (RenderThread *rt : render_threads_) {
109+
rt->CancelAllTickets();
110+
}
113111

112+
// 停止所有渲染线程(适用于所有 backend 类型)
113+
for (RenderThread *rt : render_threads_) {
114+
rt->quit();
115+
rt->wait();
116+
}
117+
118+
if (gl_thread_) {
114119
// 停止 OpenGL 线程
115120
gl_thread_->Stop();
116121
gl_thread_->wait();
@@ -248,6 +253,11 @@ void RenderManager::SetAggressiveGarbageCollection(bool enabled)
248253

249254
void RenderManager::ClearOldDecoders()
250255
{
256+
// kDummy 模式下没有 decoder cache
257+
if (!decoder_cache_) {
258+
return;
259+
}
260+
251261
QMutexLocker locker(decoder_cache_->mutex());
252262

253263
qint64 min_age =
@@ -339,6 +349,15 @@ bool RenderThread::RemoveTicket(RenderTicketPtr ticket)
339349
return true;
340350
}
341351

352+
void RenderThread::CancelAllTickets()
353+
{
354+
QMutexLocker locker(&mutex_);
355+
356+
for (auto &ticket : queue_) {
357+
ticket->Cancel();
358+
}
359+
}
360+
342361
void RenderThread::quit()
343362
{
344363
QMutexLocker locker(&mutex_);
@@ -348,6 +367,9 @@ void RenderThread::quit()
348367

349368
RenderTicketPtr RenderThread::StealFromOthers()
350369
{
370+
// 加锁保护对 s_all_threads_ 的访问
371+
QMutexLocker locker(&s_all_threads_mutex_);
372+
351373
// 快速路径:如果没有其他线程,直接返回
352374
if (s_all_threads_.size() <= 1) {
353375
return nullptr;
@@ -367,10 +389,16 @@ RenderTicketPtr RenderThread::StealFromOthers()
367389
continue;
368390
}
369391

392+
// 解锁后再调用 TrySteal,避免死锁
393+
locker.unlock();
394+
370395
RenderTicketPtr stolen_ticket;
371396
if (other->TrySteal(stolen_ticket)) {
372397
return stolen_ticket;
373398
}
399+
400+
// 重新加锁继续遍历
401+
locker.relock();
374402
}
375403

376404
return nullptr;

app/render/rendermanager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class RenderThread : public QThread {
9393

9494
bool RemoveTicket(RenderTicketPtr ticket);
9595

96+
// 取消队列中的所有任务
97+
void CancelAllTickets();
98+
9699
void quit();
97100

98101
OpenGLThread *GetGLThread() const { return gl_thread_; }

app/render/renderprocessor.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,17 @@ RenderProcessor::ResolveDecoderFromInput(const QString &decoder_id,
392392
return nullptr;
393393
}
394394

395+
// kDummy 模式下没有 decoder cache,直接创建解码器
396+
if (!decoder_cache_) {
397+
DecoderPtr dec = Decoder::CreateFromID(decoder_id);
398+
if (dec && !dec->Open(stream)) {
399+
qWarning() << "Failed to open decoder for" << stream.filename()
400+
<< "::" << stream.stream();
401+
return nullptr;
402+
}
403+
return dec;
404+
}
405+
395406
QMutexLocker locker(decoder_cache_->mutex());
396407

397408
DecoderPair decoder = decoder_cache_->value(stream);

0 commit comments

Comments
 (0)