daft-engineers / vocoder

Open source vocoder designed for the Raspberry Pi.
https://daft-engineers.github.io/vocoder/
Mozilla Public License 2.0
11 stars 0 forks source link

Message Passing #41

Closed MHCooke closed 1 year ago

MHCooke commented 1 year ago

As a daft engineer, I want to have a thread that sleeps until a message is available to be process. How do I do this?

Success Criteria:

MHCooke commented 1 year ago

James produced this code example.

#include <iostream>
#include <string>
#include <condition_variable>
#include <thread>
#include <chrono>
#include <queue>

std::condition_variable cond;
std::mutex cond_m;
bool stop_waiting = false;
std::queue<int> queue;

// cosumer
void printer() {
    // unique lock defaults to locked. 
    std::unique_lock<std::mutex> lk(cond_m);
    for (int i = 0; i < 10; i++){
        // lk must be locked, otherwise wait will result in undefined behaviour. wait unlocks it and sleeps the thread until it is woken. when woken, it checks the predicate to see if it should go back to sleep or move on. if it moves on, then it locks lk
        cond.wait(lk, []{return queue.empty() == false;});
        std::cerr << "Printing: " << queue.front() << "\n";
        queue.pop();

        // optional: in the case that more than just basic number crunching is to be done, you can manually unlock and lock
        lk.unlock();
        std::this_thread::sleep_for(std::chrono::seconds(2));
        lk.lock();

    }
}

// supplier
void signaler() {

    for (int i = 0; i < 10; i++){
        {
            // you don't specifically have to use lock_guard, but it expires at the end of it's scope, so it makes for nice RAII 
            std::lock_guard<std::mutex> lk(cond_m);
            queue.push(3+i);
            std::cerr << "Adding: " << 3+i << "\n";
        }

        // notify is used to wake up threads that are wait()ing 
        cond.notify_all();
        std::this_thread::sleep_for(std::chrono::seconds(1));

    }

    cond.notify_all();
}

int main() {
    std::thread t1(printer), t2(signaler);
    t1.join();
    t2.join();

}

(updated 21/03/23 to include a little more examples for working with the locks)

I think the next step would be to implement this into a message class, which can be passed to the threaads

Jambls commented 1 year ago

Done