Auto-cleaning file pool
This commit is contained in:
parent
e6ecbc6fcd
commit
0e24daf26d
3 changed files with 30 additions and 38 deletions
|
|
@ -342,9 +342,9 @@ sfz::FileDataHolder sfz::FilePool::loadFile(const FileId& fileId) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
sfz::FileDataHolder sfz::FilePool::getFilePromise(const FileId& fileId) noexcept
|
||||
sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr<FileId>& fileId) noexcept
|
||||
{
|
||||
const auto preloaded = preloadedFiles.find(fileId);
|
||||
const auto preloaded = preloadedFiles.find(*fileId);
|
||||
if (preloaded == preloadedFiles.end()) {
|
||||
DBG("[sfizz] File not found in the preloaded files: " << fileId);
|
||||
return {};
|
||||
|
|
@ -381,14 +381,20 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept
|
|||
{
|
||||
raiseCurrentThreadPriority();
|
||||
|
||||
std::shared_ptr<FileId> id = data.id.lock();
|
||||
if (!id) {
|
||||
// file ID was nulled, it means the region was deleted, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
const auto loadStartTime = std::chrono::high_resolution_clock::now();
|
||||
const auto waitDuration = loadStartTime - data.queuedTime;
|
||||
const fs::path file { rootDirectory / data.id.filename() };
|
||||
const fs::path file { rootDirectory / id->filename() };
|
||||
std::error_code readError;
|
||||
AudioReaderPtr reader = createAudioReader(file, data.id.isReverse(), &readError);
|
||||
AudioReaderPtr reader = createAudioReader(file, id->isReverse(), &readError);
|
||||
|
||||
if (readError) {
|
||||
DBG("[sfizz] libsndfile errored for " << data.id << " with message " << readError.message());
|
||||
DBG("[sfizz] libsndfile errored for " << *id << " with message " << readError.message());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -398,7 +404,7 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept
|
|||
while (currentStatus == FileData::Status::Invalid) {
|
||||
// Spin until the state changes
|
||||
if (spinCounter > 1024) {
|
||||
DBG("[sfizz] " << data.id << " is stuck on Invalid? Leaving the load");
|
||||
DBG("[sfizz] " << *id << " is stuck on Invalid? Leaving the load");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -418,13 +424,13 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept
|
|||
const auto frames = static_cast<uint32_t>(reader->frames());
|
||||
streamFromFile(*reader, frames, oversamplingFactor, data.data->fileData, &data.data->availableFrames);
|
||||
const auto loadDuration = std::chrono::high_resolution_clock::now() - loadStartTime;
|
||||
logger.logFileTime(waitDuration, loadDuration, frames, data.id.filename());
|
||||
logger.logFileTime(waitDuration, loadDuration, frames, id->filename());
|
||||
|
||||
data.data->status = FileData::Status::Done;
|
||||
|
||||
std::lock_guard<SpinMutex> guard { lastUsedMutex };
|
||||
if (absl::c_find(lastUsedFiles, data.id) == lastUsedFiles.end())
|
||||
lastUsedFiles.push_back(data.id);
|
||||
if (absl::c_find(lastUsedFiles, *id) == lastUsedFiles.end())
|
||||
lastUsedFiles.push_back(*id);
|
||||
}
|
||||
|
||||
void sfz::FilePool::clear()
|
||||
|
|
@ -487,20 +493,15 @@ void sfz::FilePool::dispatchingJob() noexcept
|
|||
{
|
||||
QueuedFileData queuedData;
|
||||
while (dispatchBarrier.wait(), dispatchFlag) {
|
||||
if (emptyQueueFlag) {
|
||||
while (filesToLoad.try_pop(queuedData)) {
|
||||
// pass
|
||||
}
|
||||
semEmptyQueueFinished.post();
|
||||
emptyQueueFlag = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard { loadingJobsMutex };
|
||||
|
||||
if (filesToLoad.try_pop(queuedData)) {
|
||||
loadingJobs.push_back(
|
||||
threadPool->enqueue([this](const QueuedFileData& data) { loadingJob(data); }, queuedData));
|
||||
if (!queuedData.id.lock()) {
|
||||
// file ID was nulled, it means the region was deleted, ignore
|
||||
}
|
||||
else
|
||||
loadingJobs.push_back(
|
||||
threadPool->enqueue([this](const QueuedFileData& data) { loadingJob(data); }, queuedData));
|
||||
}
|
||||
|
||||
// Clear finished jobs
|
||||
|
|
@ -521,17 +522,6 @@ void sfz::FilePool::garbageJob() noexcept
|
|||
}
|
||||
}
|
||||
|
||||
void sfz::FilePool::emptyFileLoadingQueues() noexcept
|
||||
{
|
||||
ASSERT(dispatchFlag);
|
||||
emptyQueueFlag = true;
|
||||
std::error_code ec;
|
||||
dispatchBarrier.post(ec);
|
||||
|
||||
if (!ec)
|
||||
semEmptyQueueFinished.wait();
|
||||
}
|
||||
|
||||
void sfz::FilePool::waitForBackgroundLoading() noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> guard { loadingJobsMutex };
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ public:
|
|||
* @param fileId the file to preload
|
||||
* @return FileDataHolder a file data handle
|
||||
*/
|
||||
FileDataHolder getFilePromise(const FileId& fileId) noexcept;
|
||||
FileDataHolder getFilePromise(const std::shared_ptr<FileId>& fileId) noexcept;
|
||||
/**
|
||||
* @brief Change the preloading size. This will trigger a full
|
||||
* reload of all samples, so don't call it on the audio thread.
|
||||
|
|
@ -296,7 +296,11 @@ public:
|
|||
* method on the audio thread as it will spinlock.
|
||||
*
|
||||
*/
|
||||
void emptyFileLoadingQueues() noexcept;
|
||||
void emptyFileLoadingQueues() noexcept
|
||||
{
|
||||
// nothing to do in this implementation,
|
||||
// deleting the region and its sample ID take care of it
|
||||
}
|
||||
/**
|
||||
* @brief Wait for the background loading to finish for all promises
|
||||
* in the queue.
|
||||
|
|
@ -331,9 +335,7 @@ private:
|
|||
// Signals
|
||||
volatile bool dispatchFlag { true };
|
||||
volatile bool garbageFlag { true };
|
||||
volatile bool emptyQueueFlag { false };
|
||||
RTSemaphore dispatchBarrier;
|
||||
RTSemaphore semEmptyQueueFinished;
|
||||
RTSemaphore semGarbageBarrier;
|
||||
|
||||
// Structures for the background loaders
|
||||
|
|
@ -341,13 +343,13 @@ private:
|
|||
{
|
||||
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
|
||||
QueuedFileData() = default;
|
||||
QueuedFileData(FileId id, FileData* data, TimePoint queuedTime)
|
||||
QueuedFileData(std::weak_ptr<FileId> id, FileData* data, TimePoint queuedTime)
|
||||
: id(id), data(data), queuedTime(queuedTime) {}
|
||||
QueuedFileData(const QueuedFileData&) = default;
|
||||
QueuedFileData& operator=(const QueuedFileData&) = default;
|
||||
QueuedFileData(QueuedFileData&&) = default;
|
||||
QueuedFileData& operator=(QueuedFileData&&) = default;
|
||||
FileId id {};
|
||||
std::weak_ptr<FileId> id;
|
||||
FileData* data { nullptr };
|
||||
TimePoint queuedTime {};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void sfz::Voice::startVoice(Region* region, int delay, const TriggerEvent& event
|
|||
}
|
||||
setupOscillatorUnison();
|
||||
} else {
|
||||
currentPromise = resources.filePool.getFilePromise(*region->sampleId);
|
||||
currentPromise = resources.filePool.getFilePromise(region->sampleId);
|
||||
if (!currentPromise) {
|
||||
switchState(State::cleanMeUp);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue