Async Input Stream

Hi everyone,

I am making a basic system for checking if a newer version of the plugin is available using REST API. I use the createInputStream function, but as the documentation says, it blocks the current thread. I want an asynchronous call to simultaneously hide some components and display a message that the plugin is checking for updates. I didn’t succeed with the C++ standard library async function template due to my inexperience with it. I’m sure this is a simple thing for people who have done any asynchronous programming. How would you go about implementing this?

The solution is to use a separate thread. And, in modern C++ a lambda is a nice way to handle responding to the completion of the transaction. If you just plan to do this one REST transaction then you don’t need to spend time on a general solution, but if you did you would want a class that could take the URL, the parameters, and a lambda to callback when complete (maybe an optional ‘progress’ lambda if you are going to do transfers of larger blocks of data).

Thank you for your answer. I tried multiple different ways of using a separate thread but didn’t get anything to work. I need to educate myself more about multithreading and asynchronous programming in C++. I settled upon sending the user to my website with the version number as a query string. I then retrieve the latest version there. Furthermore, it is easier to instruct the user to download the newest version since she is already on the website.
Just out of curiosity and for my learning, how would you implement the separate thread for the input stream? I mean, would you use std::async or what? Thank you again.

Since you seem inexperienced in this I am not sure what level you mean ‘how’? But I will describe at a high level.

While std::async is interesting, I am still an old school programmer who uses threads directly, so I use juce::Thread, . I have a set of REST API class which derive from the thread class, and do all the things I described above. It uses a juce::ReferenceCountedObjectPtr to maintain lifetime. While I do use the class on it’s own, I usually roll a higher level Server class that presents all of the available REST API’s as member functions. These function instantiate a ServerTransaction class and return a juce::ReferenceCountedObjectPtr to the transaction object. If you don’t keep this reference, the object will delete itself when complete, otherwise it will stay valid until you release the reference (and it is complete).

1 Like

You could do something like this:

    auto fut = std::async(std::launch::async, &Sampler::loadSample, this, file, index);
    futures.add(std::move(fut));

Where the class has a method that looks like this:

void Sampler::loadSample(juce::File file, int index)
{
    ...
}

You have to make sure that future stays alive, otherwise async will block until the ‘future’ is destroyed and the task is finished. I add it to a list in this example.
Also, you may run into lifetime problems when using this. What happens when the class will be deleted while you still are inside the task. You need to make sure that it waits in the deconstructor until the task is finished.

I finally used juce::ThreadPool like this:

    threadPool->addJob([this, file, index] { Sampler::loadSample(file, index); });

This way I don’t have to keep the future and I also don’t have any lifetime problems. Also you can create a queue when you give the thread pool only one thread.

It would be great to have IO-bound async methods when you stream something as you have in languages like c#. This way you don’t have to create a task or thread…

2 Likes