Update
Updating this ask to try and get more specific:
the easiest and most general form of the question is, can someone point me to good, freely available resources for multithreading in a DSP environment? a la lock-free etc. or help me figure out wtf is going on in Sanguine’s thread-server(there’s still a mutex hiding in there).
to go further in case someone is willing to try to explain it themselves, very basically i need help understanding how to share 2 arrays of data between 2 threads when both read and write but one cant ever be locked out.
this is the format: thread1 writes to array1 and then reads from array2 one at a time, while thread2 does block processing, reading from array1, creating new values, then writing to array2, all in one go but of course intermittently.
one caveat that potentially eases things is that i don’t think thread1 when it reads from array2 particularly cares if its a fresh value or not(while thread2 processes, thread1 has to keep pulling what are now technically old values). of course thread1 can’t ever be locked, so mutexes seem not to be the way.
However, the code below in its full form does seem to work just fine. just ran 14 instances of it with no audio issues at all and pretty good cpu usage.
original post
Hello again! this chunk of semi-pseudo code is pulled from what I have gotten to actually work for my specific case. My question is am I doing threading here any kind of ‘correctly’ or ‘safely’, like can I use this struct in multiple modules without issue, will it play well in the environment long term? so far it’s fine but i really don’t know what i’m doing here yet and this is getting into the territory where I want to be very safe.
template<typename T = float, int S = 2048>
struct FFTThreaded {
std::thread Worker;
std::mutex workTex;
std::condition_variable workCV;
std::atomic<bool> FFTReady{false};
std::atomic<bool> outReady{false};
std::atomic<bool> Quitting{false};
myRingBuffer inputBuffer<T, S>;
myRingBuffer outputBuffer<T, S>;
T FFTanalyzed[S* 2];
T FFTsynthesized[S * 2];
FFTThreaded() {
//memory setting and whatnot, then
Worker = std::thread(&FFTThreaded::processFFTThread, this);
}
~FFTThreaded() {
//I think all this is to make sure the thread closes when the program does.
{
std::lock_guard<std::mutex> lock(workTex);
Quitting.store(true);
} //lock, tell quit, unlock
workCV.notify_one();
if (Worker.joinable()) Worker.join();
}
//run on main thread every sample(must)
void push(T in) {
{
std::lock_guard<std::mutex> lock(workTex);
//put sample into inputBuffer, do the appropriate ring Buffer stuff
} //lock guard in its own scope so it unlocks on its own
//tell the worker thread when a block is ready to process
if (inputBuffer.bufferIsFull()) {
this->FFTReady.store(true);
workCV.notify_one();
}
}
//run on worker thread when needed
void processFFTThread() {
//why exactly must the thread be locked in an infinite while loop?
while (true) {
std::unique_lock<std::mutex> lock(workTex);
workCV.wait(lock, [this] {
return this->FFTReady.load();
});
if (this->Quitting) return;
//Do FFT Stuff if it says its ready, on members of this struct
//take inputBuffer into FFTanalyzed,
//alter them into FFTsynthesized
//inverse that into outputBuffer
//once its done, remind it so, and tell the output a new block is ready
this->outReady.store(true);
this->FFTReady.store(false);
lock.unlock();
}
}
//run on main thread every sample(must)
T pull() {
if (this->outReady) {
//when the output block is ready, start from the beginning of it.
}
//pull sample from the outputBuffer and return it
}
};
since i’m using this platform as my entire motivation to learn to code, it has become time to figure out multithreading and do a nice FFT. this, when expanded slightly, should become the base by which I can do any FFT effect on said worker thread. All the stuff I can find about threads is either so simplified it doesnt even complete the purpose of a thread[e.g. it forces the main thread to wait for the other to join] or beyond my ability to read as code. Summing up, again, I just need to know if i’ve done this alright.