File indexing completed on 2024-05-05 08:28:04
0001 // SPDX-FileCopyrightText: 2012-2022 The KPhotoAlbum Development Team 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include "JobManager.h" 0006 0007 #include "JobInfo.h" 0008 0009 #include <ImageManager/AsyncLoader.h> 0010 0011 #include <QThread> 0012 0013 /** 0014 \class BackgroundTaskManager::JobManager 0015 \brief Engine for running background jobs 0016 0017 This is the engine for running background jobs. Each job is a subclass of 0018 \ref BackgroundTaskManager::JobInterface. The jobs are added using \ref addJob. 0019 0020 Currently the jobs are executed one after the other on the main thread, but down the road I 0021 imagine it will provide for running jobs on secondary threads. The jobs would need to 0022 indicate that that is a possibility. 0023 */ 0024 0025 BackgroundTaskManager::JobManager *BackgroundTaskManager::JobManager::s_instance = nullptr; 0026 0027 BackgroundTaskManager::JobManager::JobManager() 0028 : m_isPaused(false) 0029 { 0030 } 0031 0032 bool BackgroundTaskManager::JobManager::shouldExecute() const 0033 { 0034 return m_queue.hasForegroundTasks() || !m_isPaused; 0035 } 0036 0037 int BackgroundTaskManager::JobManager::maxJobCount() const 0038 { 0039 // See comment in ImageManager::AsyncLoader::init() 0040 // We will at least have one active background task at the time, as some of them 0041 // currently aren't that much for background stuff. The key example of this is generating video thumbnails. 0042 const int max = qMin(3, QThread::idealThreadCount()); 0043 int count = qMax(1, max - ImageManager::AsyncLoader::instance()->activeCount() - 1); 0044 return count; 0045 } 0046 0047 void BackgroundTaskManager::JobManager::execute() 0048 { 0049 if (m_queue.isEmpty()) 0050 return; 0051 0052 if (!shouldExecute()) 0053 return; 0054 0055 while (m_active.count() < maxJobCount() && !m_queue.isEmpty()) { 0056 JobInterface *job = m_queue.dequeue(); 0057 connect(job, &JobInterface::completed, this, &JobManager::jobCompleted); 0058 m_active.append(job); 0059 Q_EMIT jobStarted(job); 0060 job->start(); 0061 } 0062 } 0063 0064 void BackgroundTaskManager::JobManager::addJob(BackgroundTaskManager::JobInterface *job) 0065 { 0066 m_queue.enqueue(job, job->priority()); 0067 execute(); 0068 } 0069 0070 BackgroundTaskManager::JobManager *BackgroundTaskManager::JobManager::instance() 0071 { 0072 if (!s_instance) 0073 s_instance = new JobManager; 0074 return s_instance; 0075 } 0076 0077 int BackgroundTaskManager::JobManager::activeJobCount() const 0078 { 0079 return m_active.count(); 0080 } 0081 0082 BackgroundTaskManager::JobInfo *BackgroundTaskManager::JobManager::activeJob(int index) const 0083 { 0084 if (index < m_active.count()) 0085 return m_active[index]; 0086 return nullptr; 0087 } 0088 0089 int BackgroundTaskManager::JobManager::futureJobCount() const 0090 { 0091 return m_queue.count(); 0092 } 0093 0094 BackgroundTaskManager::JobInfo *BackgroundTaskManager::JobManager::futureJob(int index) const 0095 { 0096 return m_queue.peek(index); 0097 } 0098 0099 bool BackgroundTaskManager::JobManager::isPaused() const 0100 { 0101 return m_isPaused; 0102 } 0103 0104 bool BackgroundTaskManager::JobManager::hasActiveJobs() const 0105 { 0106 return !m_active.isEmpty(); 0107 } 0108 0109 void BackgroundTaskManager::JobManager::jobCompleted() 0110 { 0111 JobInterface *job = qobject_cast<JobInterface *>(sender()); 0112 Q_ASSERT(job); 0113 Q_EMIT jobEnded(job); 0114 m_active.removeAll(job); 0115 job->deleteLater(); 0116 execute(); 0117 } 0118 0119 void BackgroundTaskManager::JobManager::togglePaused() 0120 { 0121 m_isPaused = !m_isPaused; 0122 execute(); 0123 } 0124 // vi:expandtab:tabstop=4 shiftwidth=4: 0125 0126 #include "moc_JobManager.cpp"