Asynchronous commands

With asynchronous commands we have typical commands from the Model View ViewModel world that return asynchronously.

Whenever that happens we want result reporting and progress reporting. We basically want something like this in QML:

Item {
  id: container
  property ViewModel viewModel: ViewModel {}

  Connections {
    target: viewModel.asyncHelloCommand
    onExecuteProgressed: {
        progressBar.value = value
        progressBar.maximumValue = maximum
    }
  }
  ProgressBar {
     id: progressBar
  }
  Button {
    enabled: viewModel.asyncHelloCommand.canExecute
    onClicked: viewModel.asyncHelloCommand.execute()
  }
}

How do we do this? First we start with defining a AbstractAsyncCommand (impl. of protected APIs here):

class AbstractAsyncCommand : public AbstractCommand {
    Q_OBJECT
public:
    AbstractAsyncCommand(QObject *parent=0);

    Q_INVOKABLE virtual QFuture<void*> executeAsync() = 0;
    virtual void execute() Q_DECL_OVERRIDE;
signals:
    void executeFinished(void* result);
    void executeProgressed(int value, int maximum);
protected:
    QSharedPointer<QFutureInterface<void*>> start();
    void progress(QSharedPointer<QFutureInterface<void*>> fut, int value, int total);
    void finish(QSharedPointer<QFutureInterface<void*>> fut, void* result);
private:
    QVector<QSharedPointer<QFutureInterface<void*>>> m_futures;
};

After that we provide an implementation:

#include <QThreadPool>
#include <QRunnable>

#include <MVVM/Commands/AbstractAsyncCommand.h>

class AsyncHelloCommand: public AbstractAsyncCommand
{
    Q_OBJECT
public:
    AsyncHelloCommand(QObject *parent=0);
    bool canExecute() const Q_DECL_OVERRIDE { return true; }
    QFuture<void*> executeAsync() Q_DECL_OVERRIDE;
private:
    void* executeAsyncTaskFunc();
    QSharedPointer<QFutureInterface<void*>> current;
    QMutex mutex;
};

#include "asynchellocommand.h"

#include <QtConcurrent/QtConcurrent>

AsyncHelloCommand::AsyncHelloCommand(QObject* parent)
    : AbstractAsyncCommand(parent) { }

void* AsyncHelloCommand::executeAsyncTaskFunc()
{
    for (int i=0; i<10; i++) {
        QThread::sleep(1);
        qDebug() << "Hello Async!";
        mutex.lock();
        progress(current, i, 10);
        mutex.unlock();
    }
    return nullptr;
}

QFuture<void*> AsyncHelloCommand::executeAsync()
{
    mutex.lock();
    current = start();
    QFutureWatcher<void*>* watcher = new QFutureWatcher<void*>(this);
    connect(watcher, &QFutureWatcher<void*>::progressValueChanged, this, [=]{
        mutex.lock();
        progress(current, watcher->progressValue(), watcher->progressMaximum());
        mutex.unlock();
    });
    connect(watcher, &QFutureWatcher<void*>::finished, this, [=]{
        void* result=watcher->result();
        mutex.lock();
        finish(current, result);
        mutex.unlock();
        watcher->deleteLater();
    });
    watcher->setFuture(QtConcurrent::run(this, &AsyncHelloCommand::executeAsyncTaskFunc));
    QFuture<void*> future = current->future();
    mutex.unlock();

    return future;
}

You can find the complete working example here.

200 cybersoldaten nodig?

Hoe lok je de gepassioneerde computernerds?

  • Zorg ervoor dat ze opleiding krijgen. Ook in zaken die niet technisch zijn. Laat toe dat ze zich verdiepen in dieptechnische zaken. Bv. low level softwareontwikkeling, electronica, en zo verder. Combineer hun (bestaande) kennis met nieuwe toepassingen. Een gepassioneerde (computer)nerd wil een leven lang bijleren en vooral: al hun kennis combineren met andere ideeën;
  • Laat toe dat ze publiek laten zien wie ze zijn en wat ze kunnen. Laat zij die dat graag doen toe dat ze op bv. radio, Internet en TV komen vertellen hoe hun werk maatschappelijk relevant is. Spreek duidelijk af wat wel en wat niet geheim moet blijven, uiteraard;
  • Zorg ervoor dat ze met regelmaat naar een hackercon of een andere conference kunnen gaan. Uiteraard zowizo bv. FOSDEM (niet echt een hackercon, maar ga er toch maar met z’n allen naartoe). Maar bv. de CCC conferences in Duitsland, SHA2017 in Nederland, en zo verder. Wees daar in ieder geval, zonder schroom, aanwezig;
  • Organiseer misschien een eigen hackercon in België. Waarom niet?
  • Maak het niet te gemakkelijk om toe te treden. Dat je er 200 nodig hebt wil niet zeggen dat de eerste de beste goed genoeg zijn;
  • Zorg ervoor dat ze goed verdienen. Begrijp dat de privé hen meer biedt dan de overheid;
  • Publiceer met regelmaat (hun) code als open source op bv. github. Bv. een Wireshark plugin of log analysetools die onze overheid gebruikt? Laat ze helpen met andere open source projecten. Kijk bv. naar hoe we onze eID software (FireFox plugins, e.d.) publiceren;
  • We hebben veel kennis van encryptie in onze universiteiten (Rijndael), stuur ze op cursus daarover bij onze cryptografen;
  • Zorg ervoor dat onze diensten géén fouten maken tegen de Belgische wetgeving. Alle echte goei zijn zo idealistisch als Edward Snowden en willen goed doen voor de samenleving. M.a.w. De wet, de privacy commissie en het Comité I doen er toe.

Veel success. Ik ben erg benieuwd.

Have confidence in yourself – technology will never replace human beings

Children aren’t worried about the future. Young people aren’t worried about the future; they’re worried about us: us leading them into the future we envision

Jack Ma — Oct 2017, keynote speech at Alibaba Cloud’s Computing Conference in Hangzhou