jeudi 28 septembre 2017

How to block thread until a function returns in another thread?

If I have a main thread and a separate, permanent worker QThread:

// Main thread where the event loop and QCoreApplication runs.
class NetworkController : public QObject {
public:
Q_OBJECT

    void connect_to_ap()
    {
        WifiAP *myAP = netMgr.get_best_ap();

        myAP->connect("my_psk_password");
    }

    // This is a class from a 3rd-party library, which contains, owns
    //  and manages the lifetime of "WifiAP" instances.
    NetworkManager netMgr;
};

// Separate thread where a state machine runs.
class StateMachineWorker : public QObject {
public:
Q_OBJECT

    void on_ready_to_connect_event()
    {
        // HERE: How to trigger NetworkController::connect_to_ap() and 
        // *block* until it returns.
    }

    NetworkController *pNetCtrlr;
}

When the state machine class enters a certain state it should connect to an AP (Access Point). The NetworkController has the functionality to connect to an AP.

I am trying to figure out a way that the state machine can do this in a thread-safe way. The problem is NetworkManager is always updating its list of WifiAP instances: they are created and destroyed often. It would not be thread-safe for StateMachineWorker to call pNetCtrlr->connect_to_ap() directly (as the NetworkManager in the NetworkController thread could at the same time delete the WifiAP instance).

So what I would like is in StateMachineWorker::on_ready_to_connect_event() to somehow signal the NetworkController to run its connect_to_ap() method in NetworkController's own thread, and to block the StateMachineWorker thread until connect_to_ap() has finished doing its stuff. The reason I want the state machine to be blocked is if I did not block and let it enter the event loop, it could receive some event that would make it transition to another state before connect_to_ap() has finished executing; this must not happen.

Mutex locks to protect the list of WifiAP in NetworkManager would not work as they would need to be inserted inside the 3rd-party library.

Aucun commentaire:

Enregistrer un commentaire