FullyLoaded status becomes independent. Added GarbageCollecting status.
This commit is contained in:
parent
f8f13f464c
commit
c566631379
2 changed files with 58 additions and 67 deletions
|
|
@ -334,11 +334,9 @@ bool sfz::FilePool::preloadFile(const FileId& fileId, uint32_t maxOffset) noexce
|
||||||
if (existingFile != preloadedFiles.end()) {
|
if (existingFile != preloadedFiles.end()) {
|
||||||
auto& fileData = existingFile->second;
|
auto& fileData = existingFile->second;
|
||||||
if (framesToLoad > fileData.preloadedData.getNumFrames()) {
|
if (framesToLoad > fileData.preloadedData.getNumFrames()) {
|
||||||
preloadedFiles[fileId].information.maxOffset = maxOffset;
|
fileData.information.maxOffset = maxOffset;
|
||||||
preloadedFiles[fileId].preloadedData = readFromFile(*reader, framesToLoad);
|
fileData.preloadedData = readFromFile(*reader, framesToLoad);
|
||||||
if (frames == framesToLoad && fileData.status != FileData::Status::FullLoaded)
|
fileData.fullyLoaded = frames == framesToLoad;
|
||||||
// Forced overwrite status
|
|
||||||
fileData.status = FileData::Status::FullLoaded;
|
|
||||||
}
|
}
|
||||||
fileData.preloadCallCount++;
|
fileData.preloadCallCount++;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -348,9 +346,9 @@ bool sfz::FilePool::preloadFile(const FileId& fileId, uint32_t maxOffset) noexce
|
||||||
*fileInformation
|
*fileInformation
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initially set status
|
|
||||||
insertedPair.first->second.status = frames == framesToLoad ? FileData::Status::FullLoaded : FileData::Status::Preloaded;
|
|
||||||
insertedPair.first->second.preloadCallCount++;
|
insertedPair.first->second.preloadCallCount++;
|
||||||
|
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||||
|
insertedPair.first->second.fullyLoaded = framesToLoad == frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -404,9 +402,9 @@ sfz::FileDataHolder sfz::FilePool::loadFile(const FileId& fileId) noexcept
|
||||||
readFromFile(*reader, frames),
|
readFromFile(*reader, frames),
|
||||||
*fileInformation
|
*fileInformation
|
||||||
});
|
});
|
||||||
// Initially set status
|
|
||||||
insertedPair.first->second.status = FileData::Status::FullLoaded;
|
|
||||||
insertedPair.first->second.preloadCallCount++;
|
insertedPair.first->second.preloadCallCount++;
|
||||||
|
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||||
|
insertedPair.first->second.fullyLoaded = true;
|
||||||
return { &insertedPair.first->second };
|
return { &insertedPair.first->second };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,9 +421,9 @@ sfz::FileDataHolder sfz::FilePool::loadFromRam(const FileId& fileId, const std::
|
||||||
readFromFile(*reader, frames),
|
readFromFile(*reader, frames),
|
||||||
*fileInformation
|
*fileInformation
|
||||||
});
|
});
|
||||||
// Initially set status
|
|
||||||
insertedPair.first->second.status = FileData::Status::FullLoaded;
|
|
||||||
insertedPair.first->second.preloadCallCount++;
|
insertedPair.first->second.preloadCallCount++;
|
||||||
|
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||||
|
insertedPair.first->second.fullyLoaded = true;
|
||||||
DBG("Added a file " << fileId.filename());
|
DBG("Added a file " << fileId.filename());
|
||||||
return { &insertedPair.first->second };
|
return { &insertedPair.first->second };
|
||||||
}
|
}
|
||||||
|
|
@ -443,7 +441,7 @@ sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr<FileId>&
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& fileData = preloaded->second;
|
auto& fileData = preloaded->second;
|
||||||
if (fileData.status != FileData::Status::FullLoaded) {
|
if (!fileData.fullyLoaded) {
|
||||||
QueuedFileData queuedData { fileId, &fileData };
|
QueuedFileData queuedData { fileId, &fileData };
|
||||||
if (!filesToLoad->try_push(queuedData)) {
|
if (!filesToLoad->try_push(queuedData)) {
|
||||||
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad->capacity() << ")");
|
DBG("[sfizz] Could not enqueue the file to load for " << fileId << " (queue capacity " << filesToLoad->capacity() << ")");
|
||||||
|
|
@ -474,17 +472,7 @@ void sfz::FilePool::setPreloadSize(uint32_t preloadSize) noexcept
|
||||||
const uint32_t frames = static_cast<uint32_t>(reader->frames());
|
const uint32_t frames = static_cast<uint32_t>(reader->frames());
|
||||||
const uint32_t framesToLoad = min(frames, maxOffset + preloadSize);
|
const uint32_t framesToLoad = min(frames, maxOffset + preloadSize);
|
||||||
fileData.preloadedData = readFromFile(*reader, framesToLoad);
|
fileData.preloadedData = readFromFile(*reader, framesToLoad);
|
||||||
|
fileData.fullyLoaded = frames == framesToLoad;
|
||||||
FileData::Status status = fileData.status;
|
|
||||||
bool fullLoaded = frames == framesToLoad;
|
|
||||||
if (fullLoaded && status != FileData::Status::FullLoaded) {
|
|
||||||
// Forced overwrite status
|
|
||||||
fileData.status = FileData::Status::FullLoaded;
|
|
||||||
}
|
|
||||||
else if (!fullLoaded && status == FileData::Status::FullLoaded) {
|
|
||||||
// Exchange status
|
|
||||||
fileData.status.compare_exchange_strong(status, FileData::Status::Preloaded);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,9 +495,12 @@ void sfz::FilePool::loadingJob(const QueuedFileData& data) noexcept
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileData::Status currentStatus = data.data->status.load();
|
FileData::Status currentStatus;
|
||||||
|
|
||||||
unsigned spinCounter { 0 };
|
unsigned spinCounter { 0 };
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
currentStatus = data.data->status.load();
|
||||||
while (currentStatus == FileData::Status::Invalid) {
|
while (currentStatus == FileData::Status::Invalid) {
|
||||||
// Spin until the state changes
|
// Spin until the state changes
|
||||||
if (spinCounter > 1024) {
|
if (spinCounter > 1024) {
|
||||||
|
|
@ -521,21 +512,23 @@ void sfz::FilePool::loadingJob(const QueuedFileData& data) noexcept
|
||||||
currentStatus = data.data->status.load();
|
currentStatus = data.data->status.load();
|
||||||
spinCounter += 1;
|
spinCounter += 1;
|
||||||
}
|
}
|
||||||
|
// wait for garbage collection
|
||||||
|
if (currentStatus == FileData::Status::GarbageCollecting) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Already loading or loaded
|
// Already loading or loaded
|
||||||
if (currentStatus != FileData::Status::Preloaded)
|
if (currentStatus != FileData::Status::Preloaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Someone else got the token
|
// go outside loop if this gets token
|
||||||
if (!data.data->status.compare_exchange_strong(currentStatus, FileData::Status::Streaming))
|
if (data.data->status.compare_exchange_strong(currentStatus, FileData::Status::Streaming))
|
||||||
return;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
streamFromFile(*reader, data.data->fileData, &data.data->availableFrames);
|
streamFromFile(*reader, data.data->fileData, &data.data->availableFrames);
|
||||||
|
|
||||||
currentStatus = data.data->status.load();
|
data.data->status = FileData::Status::Done;
|
||||||
if (currentStatus == FileData::Status::Streaming) {
|
|
||||||
data.data->status.compare_exchange_strong(currentStatus, FileData::Status::Done);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<SpinMutex> guard { garbageAndLastUsedMutex };
|
std::lock_guard<SpinMutex> guard { garbageAndLastUsedMutex };
|
||||||
if (absl::c_find(lastUsedFiles, *id) == lastUsedFiles.end())
|
if (absl::c_find(lastUsedFiles, *id) == lastUsedFiles.end())
|
||||||
|
|
@ -650,8 +643,7 @@ void sfz::FilePool::setRamLoading(bool loadInRam) noexcept
|
||||||
*reader,
|
*reader,
|
||||||
fileData.information.end
|
fileData.information.end
|
||||||
);
|
);
|
||||||
// Initially set status
|
fileData.fullyLoaded = true;
|
||||||
fileData.status = FileData::Status::FullLoaded;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPreloadSize(preloadSize);
|
setPreloadSize(preloadSize);
|
||||||
|
|
@ -681,31 +673,29 @@ void sfz::FilePool::triggerGarbageCollection() noexcept
|
||||||
if (data.readerCount != 0)
|
if (data.readerCount != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto status = data.status.load();
|
|
||||||
if (data.availableFrames == 0) {
|
|
||||||
return status == FileData::Status::Preloaded || status == FileData::Status::FullLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(status) {
|
|
||||||
case FileData::Status::Invalid:
|
|
||||||
case FileData::Status::Streaming:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto secondsIdle = std::chrono::duration_cast<std::chrono::seconds>(now - data.lastViewerLeftAt).count();
|
const auto secondsIdle = std::chrono::duration_cast<std::chrono::seconds>(now - data.lastViewerLeftAt).count();
|
||||||
if (secondsIdle < config::fileClearingPeriod)
|
if (secondsIdle < config::fileClearingPeriod)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Queue garbage collection
|
auto status = data.status.load();
|
||||||
// At first set availableFromes to 0
|
if (status == FileData::Status::Preloaded) {
|
||||||
// Then forced set status
|
// do the garbage collection when availableFrames != 0
|
||||||
data.availableFrames = 0;
|
if (data.availableFrames == 0) {
|
||||||
if (status != FileData::Status::FullLoaded)
|
|
||||||
data.status = FileData::Status::Preloaded;
|
|
||||||
garbageToCollect.push_back(std::move(data.fileData));
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (status != FileData::Status::Done) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do garbage collection when changing the status is success
|
||||||
|
if (data.status.compare_exchange_strong(status, FileData::Status::GarbageCollecting)) {
|
||||||
|
data.availableFrames = 0;
|
||||||
|
garbageToCollect.push_back(std::move(data.fileData));
|
||||||
|
data.status = FileData::Status::Preloaded;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ struct FileInformation {
|
||||||
// Strict C++11 disallows member initialization if aggregate initialization is to be used...
|
// Strict C++11 disallows member initialization if aggregate initialization is to be used...
|
||||||
struct FileData
|
struct FileData
|
||||||
{
|
{
|
||||||
enum class Status { Invalid, Preloaded, Streaming, Done, FullLoaded };
|
enum class Status { Invalid, Preloaded, Streaming, Done, GarbageCollecting };
|
||||||
FileData() = default;
|
FileData() = default;
|
||||||
FileData(FileAudioBuffer preloaded, FileInformation info)
|
FileData(FileAudioBuffer preloaded, FileInformation info)
|
||||||
: preloadedData(std::move(preloaded)), information(std::move(info))
|
: preloadedData(std::move(preloaded)), information(std::move(info))
|
||||||
|
|
@ -113,6 +113,7 @@ struct FileData
|
||||||
FileAudioBuffer fileData {};
|
FileAudioBuffer fileData {};
|
||||||
int preloadCallCount { 0 };
|
int preloadCallCount { 0 };
|
||||||
std::atomic<Status> status { Status::Invalid };
|
std::atomic<Status> status { Status::Invalid };
|
||||||
|
bool fullyLoaded { false };
|
||||||
std::atomic<size_t> availableFrames { 0 };
|
std::atomic<size_t> availableFrames { 0 };
|
||||||
std::atomic<int> readerCount { 0 };
|
std::atomic<int> readerCount { 0 };
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> lastViewerLeftAt;
|
std::chrono::time_point<std::chrono::high_resolution_clock> lastViewerLeftAt;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue