multithreading with BlackBerry 10 and Qt

We are hard at work on the BlackBerry 10 Native SDK helper class for cloudbase.io – this means C++ and Qt. It has been a learning process and we thought we’d share some of our newly found wisdom.

ApplicationPrivate::resourceManager: ERROR called from non-UI thread QThread…

How many times have we seen this? When we began working on the helper class we were relatively new to Qt development. Let’s face it, BlackBerry specific information is not exactly abundant on the net. So here’s our simple tutorial.

For the purpose of this example and the cloudbase.io helper class the scenario is fairly simple. The CBHelper object – i.e. the helper class – runs on the main UI thread. Whenever an API is called, a CBHttpConnection object handles the request and the response. The HttpConnection object implements QThread, this way the entire http connection is executed asynchronously without slowing down the main UI thread.

Once the processing is completed we need to call a method on the CBHelperResponder object, which was passed to the helper class to manage the response. This method may very well need to update the application’s GUI. We need to get back to the main UI thread!

BlackBerry 10 async messages diagram

The Qt libraries used by the BlackBerry 10 Native SDK have implemented this in the form of SIGNALS and SLOTS. Any class inheriting from QObject will be able to declare a number of SIGNALS it can emit as well as SLOTS to receive these SIGNALS.

You will have noticed that what we have been writing is not exactly standard C++ syntax and keywords. The Q_OBJECT, Q_SLOTS and Q_SIGNALS macros we have put in our class declaration will be used to generate meta-object information by a Qt utility aptly named MOC (Meta Object Compiler). Moc will process our headers and generate as output additional header files with all the information Qt needs to connect the SIGNALS and SLOTS and trigger them. The BlackBerry 10 documentation has an extensive guide on how to use moc and automate it in your project’s Makefile. In this example we will manually run moc over the two headers we have modified, CBHelper.h and CBHttpConnection.h.

The moc tool is located under your BlackBerry SDK installation folder in the host_xx_x_xx_xxx/${HOST_OS}/${HOST_CPU}/usr/bin – We are building this on a MacBook Pro so our path will be /Applications/bbndk/host_10_0_10_534/darwin/x86/usr/bin/moc

Now that we have generated the two new .moc files we can include them in our source. We will add them at the bottom of the implementation files for the two classes. For example, at the bottom of CBHelper.cpp we will add the #include “CBHelper.moc” instruction.

We are nearly there. All we have to do now is tell Qt how to connect the dots and associate the requestCompleted SIGNAL with the handleRequestCompleted SLOT in the CBHelper object. We do not need to implement the requestCompleted SIGNAL as it is there only as a declaration. We will add the implementation of the SLOT to the CBHelper.cpp file.

There is only one thing left to do. Emit the signal from the CBHttpConnection class. This couldn’t be easier. Emit’s the keyword.

Hope this was helpful.

Happy coding.

The Team @ cloudbase.io