c++qtqfuture

QT c++ QFutures with signals without QConcurrent, like promises/observables?


I'm fuguring out how to use Futures with non-blocking event driven code (in a separate thread or not, both) but how can i end the future from a slot (~resolve the promise based on an signal) ?

QByteArray RfidCardReader::startTask(QByteArray send)
{
    if(this->busy==false) {
        this->sendFrame(send);

        QObject::connect(this, &RfidCardReader::frameReady,
        [=]() {/*this must be the startTask return*/ return this->int_read_buffer;});

    } else {
        throw 0;//Handle a queue instead
    }
}

QFuture<QByteArray> RfidCardReader::send(QByteArray passed_send)
{
    return QtConcurrent::run(QThreadPool::globalInstance(), this->startTask, passed_send);

}

basically what I want to do using only an instance is wrap a serial device (whic is sync by nature) in a queue of Futures but with only non blocking code using signals like &QIODevice::bytesWritten &QIODevice::readyRead etc... if there are better approches to the problem let me know, i would be glad to know the right way to write readable async code in Qt without blocking in separate threads


Solution

  • A serial device is asynchronous by nature, and using the serial port concurrently from multiple threads is undefined behavior. You can certainly resolve futures from any thread, but there's nothing in Qt that will give you a future on the same thread. Recall that a QFuture is not a class that you can sensibly instantiate. The default-constructed class is useless.

    To get an idea of how to handle asynchronous serial I/O, see for example this answer.

    Then you can use the undocumented <QFutureInterface> header, and create your own implementation that can wrap higher-level aspects of your protocol, i.e. commands/requests. You could then group such futures, and use a single watcher to determine when they are done.

    Your approach is quite interesting in fact, and I might develop a complete example.