render: dedicate thread to audio production
Prevents audio from getting stalled behind slow video jobs
This commit is contained in:
@@ -29,52 +29,67 @@ ThreadPool::ThreadPool(unsigned threads, QObject *parent) :
|
||||
threads = std::thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
available_count_ = threads;
|
||||
for (unsigned i = 0; i < threads; i += 1) {
|
||||
worker_threads_.emplace_back(std::bind(&ThreadPool::thread_exec, this));
|
||||
worker_threads_.emplace_back(std::bind(&ThreadPool::thread_exec, this, &tasks_, &task_mutex_, &cond_));
|
||||
}
|
||||
|
||||
// Make single reserved thread for high priority tasks (usually audio) so they don't get stuck
|
||||
// behind a lot of slow tasks
|
||||
high_thread_ = std::thread(std::thread(std::bind(&ThreadPool::thread_exec, this, &high_tasks_, &high_mutex_, &high_cond_)));
|
||||
}
|
||||
|
||||
void ThreadPool::AddTicket(RenderTicketPtr ticket, RenderTicketPriority priority)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(task_mutex_);
|
||||
|
||||
if (priority == RenderTicketPriority::kHigh) {
|
||||
tasks_.emplace_front(std::move(ticket));
|
||||
std::lock_guard<std::mutex> lock(high_mutex_);
|
||||
high_tasks_.emplace_back(std::move(ticket));
|
||||
high_cond_.notify_one();
|
||||
} else {
|
||||
std::lock_guard<std::mutex> lock(task_mutex_);
|
||||
tasks_.emplace_back(std::move(ticket));
|
||||
cond_.notify_one();
|
||||
}
|
||||
|
||||
cond_.notify_one();
|
||||
}
|
||||
|
||||
bool ThreadPool::RemoveTicket(RenderTicketPtr ticket)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(task_mutex_);
|
||||
|
||||
const auto it = std::find(tasks_.begin(), tasks_.end(), ticket);
|
||||
if (it == tasks_.end()) {
|
||||
return false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(task_mutex_);
|
||||
const auto it = std::find(tasks_.begin(), tasks_.end(), ticket);
|
||||
if (it != tasks_.end()) {
|
||||
tasks_.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tasks_.erase(it);
|
||||
return true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(high_mutex_);
|
||||
const auto it = std::find(high_tasks_.begin(), high_tasks_.end(), ticket);
|
||||
if (it != high_tasks_.end()) {
|
||||
high_tasks_.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ThreadPool::thread_exec()
|
||||
void ThreadPool::thread_exec(std::deque<TaskType> *queue, std::mutex *mutex, std::condition_variable *cond)
|
||||
{
|
||||
while (true) {
|
||||
TaskType task;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(task_mutex_);
|
||||
cond_.wait(lock, [this]{ return this->end_threadp_ || !this->tasks_.empty(); });
|
||||
std::unique_lock<std::mutex> lock(*mutex);
|
||||
cond->wait(lock, [this, queue]{ return this->end_threadp_ || !queue->empty(); });
|
||||
|
||||
if (this->end_threadp_ && this->tasks_.empty()) {
|
||||
if (this->end_threadp_ && queue->empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
task = std::move(tasks_.front());
|
||||
tasks_.pop_front();
|
||||
task = std::move(queue->front());
|
||||
queue->pop_front();
|
||||
}
|
||||
|
||||
RunTicket(task);
|
||||
@@ -85,10 +100,12 @@ ThreadPool::~ThreadPool()
|
||||
{
|
||||
end_threadp_ = true;
|
||||
cond_.notify_all();
|
||||
high_cond_.notify_all();
|
||||
|
||||
for (auto &e : worker_threads_) {
|
||||
e.join();
|
||||
}
|
||||
high_thread_.join();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,13 +49,20 @@ public:
|
||||
virtual ~ThreadPool() override;
|
||||
|
||||
private:
|
||||
void thread_exec();
|
||||
void thread_exec(std::deque<TaskType> *queue, std::mutex *mutex, std::condition_variable *cond);
|
||||
|
||||
std::vector<std::thread> worker_threads_;
|
||||
std::deque<TaskType> tasks_;
|
||||
std::mutex task_mutex_;
|
||||
std::condition_variable cond_;
|
||||
|
||||
std::thread high_thread_;
|
||||
std::deque<TaskType> high_tasks_;
|
||||
std::mutex high_mutex_;
|
||||
std::condition_variable high_cond_;
|
||||
|
||||
std::atomic_bool end_threadp_{false};
|
||||
std::atomic_int available_count_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1492,10 +1492,11 @@ void ViewerWidget::PlaybackTimerUpdate()
|
||||
}
|
||||
|
||||
if (IsPlaying()) {
|
||||
int count = 0;
|
||||
for (int i=display_widget_->queue()->size(); i<DeterminePlaybackQueueSize(); i++) {
|
||||
RequestNextFrameForQueue();
|
||||
count++;
|
||||
while (queue_watchers_.size() < DeterminePlaybackQueueSize()) {
|
||||
if (!RequestNextFrameForQueue()) {
|
||||
// Prevent infinite loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user