Search code examples
c++multithreadingqtsignals-slotspolling

How do I start polling with mutex locked thread in QT?


I am using Ubuntu 12.04 with Qt version 4.8.3. In Qt main window I manage to open my devices and this part of the code is working. Now after I open devices I need to wait if a card is present. It means I have to use polling to get the data from card. But the polling must be infinite loop. Polling for card arrival and removal.

Example poll for card arrival every 20ms and when a card is detected I need to switch poll for card removal every 20 ms. So when a card arrival or removal is detected, my app signals Qt event such that another Qt thread can now proceed to read/write the card.

I read about QThread, mutex locked so on and I am bit confused. I have a main window plus a worker class. In my mainwindow I code as;

// Open a reader (from my SDK)
cReader.open 

//If the reader is open use;

thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect(worker,SIGNAL(??????),SLOT(?????);
connect(worker,SIGNAL(?????),SLOT(?????);
.........

First I must use connect for SIGNAL/SLOT and start the card arrival/removal polling. Than if any card detected I have signal to another thread to read from card or write into the card.

So I don’t know where to start or how to call signal/slot? I need help to fill the ?????? above SIGNAL/SLOT.

Edited: I also need mutex lock shared by the polling thread and the card handiling thread. This is because a card poll command will invalidate my mifare session if opened.

Any help please, Kind Regards,


Solution

  • It is not thread-safe (unless one QObject accesses data in another QObject and both belong to the same thread).

    In terms of usage of mutexes the QMutexLocker is your friend and I advise you to use it instead of manually handling the locking/unlocking.

    If you re-read your question you will notice that you heavily use intervals. And how do we handle intervals? Using QTimer. Here is my suggestion:

    • Create a QTimer along with the worker QObject
    • Set the interval of the timer to 20ms or whatever interval you want for it to tigger an event; a timer with interval set to 0 means that an event will be triggered by it as soon as possible
    • Connect the timer to the slot of the worker that does the work (check if card is removed etc.)
    • Connect the object's slots/signals to the signals/slots of your UI (using QMutexLocker will enable you to secure the access on the internal data of both) or another QObject (in the same or a different thread where the worker is residing)
    • Move both the timer and worker to a QThread and start the thread

    The timer will start triggering a check for your card every X milliseconds. The worker will then receive that signal from the timer (here no mutex is required since both the timer and the worker are with the same thread-affinity). Things will change internally for the worker and then it will emit a signal to another QObject or the UI itself. At this point the mutexes come into play unless you are accessing another instance of a QObject in the same thread where your worker is.

    You can add as many threads as you like by doing so. I have a UI that has 6 threads running in the background accessing both the UI and each other without any problem using timers.

    EDIT: I have started working on a small demo using QTimer, QThread and QObject. Application is incomplete/buggy but you can see how QTimer works.