mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Fix an edge case where m_remainingItems has elements but we don't have more workers to consume it
This commit is contained in:
parent
dbae196f2d
commit
30798435d1
@ -203,6 +203,13 @@ ThumbnailGenerator* ThumbnailGenerator::instance()
|
|||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThumbnailGenerator::ThumbnailGenerator()
|
||||||
|
{
|
||||||
|
int n = std::thread::hardware_concurrency()-1;
|
||||||
|
if (n < 1) n = 1;
|
||||||
|
m_maxWorkers = n;
|
||||||
|
}
|
||||||
|
|
||||||
bool ThumbnailGenerator::checkWorkers()
|
bool ThumbnailGenerator::checkWorkers()
|
||||||
{
|
{
|
||||||
base::scoped_lock hold(m_workersAccess);
|
base::scoped_lock hold(m_workersAccess);
|
||||||
@ -231,17 +238,31 @@ void ThumbnailGenerator::generateThumbnail(IFileItem* fileitem)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (fileitem->getThumbnailProgress() > 0.0) {
|
if (fileitem->getThumbnailProgress() > 0.0) {
|
||||||
if (fileitem->getThumbnailProgress() < 0.0002) {
|
if (fileitem->getThumbnailProgress() == 0.00001) {
|
||||||
m_remainingItems.prioritize(
|
m_remainingItems.prioritize(
|
||||||
[fileitem](const Item& item) {
|
[fileitem](const Item& item) {
|
||||||
return (item.fileitem == fileitem);
|
return (item.fileitem == fileitem);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If there is no more workers running, we have to start a new
|
||||||
|
// one to process the m_remainingItems queue. How is it possible
|
||||||
|
// that a IFileItem has a thumbnail progress == 0.00001 but
|
||||||
|
// there is no workers? This is an edge case where:
|
||||||
|
// 1. The Worker::loadBgThread() asks for the queue of remaining items
|
||||||
|
// and it's empty, so the thread is going to be closed
|
||||||
|
// 2. We've just created a FOP for this IFileItem and ask for
|
||||||
|
// available workers and we've already launch the max quantity
|
||||||
|
// of possible workers (m_maxWorkers)
|
||||||
|
// 3. All worker threads are just closed so there is no more
|
||||||
|
// worker for the remaining item in the queue.
|
||||||
|
if (m_workers.empty())
|
||||||
|
startWorker();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a starting progress so we don't enqueue the same item two times.
|
// Set a starting progress so we don't enqueue the same item two times.
|
||||||
fileitem->setThumbnailProgress(0.0001);
|
fileitem->setThumbnailProgress(0.00001);
|
||||||
|
|
||||||
THUMB_TRACE("Queue FOP thumbnail for %s\n",
|
THUMB_TRACE("Queue FOP thumbnail for %s\n",
|
||||||
fileitem->fileName().c_str());
|
fileitem->fileName().c_str());
|
||||||
@ -261,19 +282,7 @@ void ThumbnailGenerator::generateThumbnail(IFileItem* fileitem)
|
|||||||
m_remainingItems.push(Item(fileitem, fop.get()));
|
m_remainingItems.push(Item(fileitem, fop.get()));
|
||||||
fop.release();
|
fop.release();
|
||||||
|
|
||||||
int n = std::thread::hardware_concurrency()-1;
|
startWorker();
|
||||||
if (n < 1) n = 1;
|
|
||||||
if (m_workers.size() < n) {
|
|
||||||
Worker* worker = new Worker(m_remainingItems);
|
|
||||||
try {
|
|
||||||
base::scoped_lock hold(m_workersAccess);
|
|
||||||
m_workers.push_back(worker);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
delete worker;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThumbnailGenerator::stopAllWorkers()
|
void ThumbnailGenerator::stopAllWorkers()
|
||||||
@ -296,4 +305,14 @@ void ThumbnailGenerator::stopAllWorkers()
|
|||||||
worker->stop();
|
worker->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThumbnailGenerator::startWorker()
|
||||||
|
{
|
||||||
|
base::scoped_lock hold(m_workersAccess);
|
||||||
|
if (m_workers.size() < m_maxWorkers) {
|
||||||
|
std::unique_ptr<Worker> worker(new Worker(m_remainingItems));
|
||||||
|
m_workers.push_back(worker.get());
|
||||||
|
worker.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
@ -24,6 +24,7 @@ namespace app {
|
|||||||
class IFileItem;
|
class IFileItem;
|
||||||
|
|
||||||
class ThumbnailGenerator {
|
class ThumbnailGenerator {
|
||||||
|
ThumbnailGenerator();
|
||||||
public:
|
public:
|
||||||
static ThumbnailGenerator* instance();
|
static ThumbnailGenerator* instance();
|
||||||
|
|
||||||
@ -43,6 +44,8 @@ namespace app {
|
|||||||
void stopAllWorkers();
|
void stopAllWorkers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void startWorker();
|
||||||
|
|
||||||
class Worker;
|
class Worker;
|
||||||
typedef std::vector<Worker*> WorkerList;
|
typedef std::vector<Worker*> WorkerList;
|
||||||
|
|
||||||
@ -56,6 +59,7 @@ namespace app {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int m_maxWorkers;
|
||||||
WorkerList m_workers;
|
WorkerList m_workers;
|
||||||
base::mutex m_workersAccess;
|
base::mutex m_workersAccess;
|
||||||
std::unique_ptr<base::thread> m_stopThread;
|
std::unique_ptr<base::thread> m_stopThread;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user