The file promise logic actually allocated
Changed to add a pool of "empty" promises, but I wonder if all of this could be made a bit simpler?
This commit is contained in:
parent
13f9baed33
commit
7379ba37c0
3 changed files with 60 additions and 18 deletions
|
|
@ -40,6 +40,7 @@ namespace config {
|
|||
constexpr int numBackgroundThreads { 4 };
|
||||
constexpr int numVoices { 64 };
|
||||
constexpr int maxVoices { 256 };
|
||||
constexpr int maxFilePromises { maxVoices * 2 };
|
||||
constexpr int sustainCC { 64 };
|
||||
constexpr int allSoundOffCC { 120 };
|
||||
constexpr int resetCC { 121 };
|
||||
|
|
|
|||
|
|
@ -89,7 +89,11 @@ sfz::FilePool::FilePool()
|
|||
{
|
||||
for (int i = 0; i < config::numBackgroundThreads; ++i)
|
||||
threadPool.emplace_back( &FilePool::loadingThread, this );
|
||||
|
||||
threadPool.emplace_back( &FilePool::clearingThread, this );
|
||||
|
||||
for (int i = 0; i < config::maxFilePromises; ++i)
|
||||
emptyPromises.push_back(std::make_shared<FilePromise>());
|
||||
}
|
||||
|
||||
sfz::FilePool::~FilePool()
|
||||
|
|
@ -161,15 +165,21 @@ bool sfz::FilePool::preloadFile(const std::string& filename, uint32_t maxOffset)
|
|||
|
||||
sfz::FilePromisePtr sfz::FilePool::getFilePromise(const std::string& filename) noexcept
|
||||
{
|
||||
auto promise = std::make_shared<FilePromise>();
|
||||
if (emptyPromises.empty())
|
||||
return {};
|
||||
|
||||
const auto preloaded = preloadedFiles.find(filename);
|
||||
if (preloaded != preloadedFiles.end()) {
|
||||
promise->filename = preloaded->first;
|
||||
promise->preloadedData = preloaded->second.preloadedData;
|
||||
promise->sampleRate = preloaded->second.sampleRate;
|
||||
promise->oversamplingFactor = oversamplingFactor;
|
||||
promiseQueue.try_enqueue(promise);
|
||||
}
|
||||
if (preloaded == preloadedFiles.end())
|
||||
return {};
|
||||
|
||||
auto& promise = emptyPromises.back();
|
||||
promise->filename = preloaded->first;
|
||||
promise->preloadedData = preloaded->second.preloadedData;
|
||||
promise->sampleRate = preloaded->second.sampleRate;
|
||||
promise->oversamplingFactor = oversamplingFactor;
|
||||
promiseQueue.try_enqueue(promise);
|
||||
emptyPromises.pop_back();
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +203,10 @@ void sfz::FilePool::tryToClearPromises()
|
|||
while (addingPromisesToClear)
|
||||
std::this_thread::sleep_for(1ms);
|
||||
|
||||
promisesToClear.clear();
|
||||
for (auto& promise: promisesToClear) {
|
||||
if (promise->dataReady)
|
||||
promise->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void sfz::FilePool::clearingThread()
|
||||
|
|
@ -261,21 +274,37 @@ void sfz::FilePool::cleanupPromises() noexcept
|
|||
if (!canAddPromisesToClear)
|
||||
return;
|
||||
|
||||
// The garbage collection cleared the data from these so we can move them
|
||||
// back to the empty queue
|
||||
auto clearedIterator = promisesToClear.begin();
|
||||
auto clearedSentinel = promisesToClear.end() - 1;
|
||||
while (clearedIterator != promisesToClear.end()) {
|
||||
if (clearedIterator->get()->dataReady == false) {
|
||||
emptyPromises.push_back(*clearedIterator);
|
||||
std::iter_swap(clearedIterator, clearedSentinel);
|
||||
clearedSentinel--;
|
||||
promisesToClear.pop_back();
|
||||
} else {
|
||||
clearedIterator++;
|
||||
}
|
||||
}
|
||||
|
||||
FilePromisePtr promise;
|
||||
// Remove stuff from the filled queue and put them in a linear storage
|
||||
// Remove the promises from the filled queue and put them in a linear
|
||||
// storage
|
||||
while (filledPromiseQueue.try_dequeue(promise))
|
||||
temporaryFilePromises.push_back(promise);
|
||||
|
||||
auto promiseIterator = temporaryFilePromises.begin();
|
||||
auto sentinel = temporaryFilePromises.end() - 1;
|
||||
while (promiseIterator != temporaryFilePromises.end()) {
|
||||
if (promiseIterator->use_count() == 1) {
|
||||
promisesToClear.push_back(*promiseIterator);
|
||||
std::iter_swap(promiseIterator, sentinel);
|
||||
sentinel--;
|
||||
auto filledIterator = temporaryFilePromises.begin();
|
||||
auto filledSentinel = temporaryFilePromises.end() - 1;
|
||||
while (filledIterator != temporaryFilePromises.end()) {
|
||||
if (filledIterator->use_count() == 1) {
|
||||
promisesToClear.push_back(*filledIterator);
|
||||
std::iter_swap(filledIterator, filledSentinel);
|
||||
filledSentinel--;
|
||||
temporaryFilePromises.pop_back();
|
||||
} else {
|
||||
promiseIterator++;
|
||||
filledIterator++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,17 @@ struct FilePromise
|
|||
return AudioSpan<const float>(*preloadedData);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
fileData.reset();
|
||||
preloadedData.reset();
|
||||
filename = "";
|
||||
availableFrames = 0;
|
||||
dataReady = false;
|
||||
oversamplingFactor = config::defaultOversamplingFactor;
|
||||
sampleRate = config::defaultSampleRate;
|
||||
}
|
||||
|
||||
absl::string_view filename {};
|
||||
AudioBufferPtr preloadedData {};
|
||||
AudioBuffer<float> fileData {};
|
||||
|
|
@ -214,6 +225,7 @@ private:
|
|||
std::atomic<int> threadsLoading { 0 };
|
||||
|
||||
// File promises data structures along with their guards.
|
||||
std::vector<FilePromisePtr> emptyPromises;
|
||||
std::vector<FilePromisePtr> temporaryFilePromises;
|
||||
std::vector<FilePromisePtr> promisesToClear;
|
||||
std::atomic<bool> addingPromisesToClear { false };
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue