Communication between QThread and boost threads

The Gui is in Qt and Api is in boost. The Gui is meant to sit on top of Api. One of the functions of Api is to do network level data management, process data in certain ways and communicate with the Gui (ie., bridge Gui with other end of Api). To keep the GUI from freezing Api does it's work in a separate thread. If both Gui and Api had used Qt, communication would have been easier with cross-threaded signal-slot mechanism of Qt. Api emits and returns immediately and vice-versa. So none would be blocked unless explicitly specified (*Qt::BlockingQueuedConnection*). I've been using boost only since a while back as it was required to code new Api in boost. How do i achieve this mechanism in *boost <--> Qt communication*? Api is going to be header+static_library and so Gui and Api will produce single executable. I have to support Linux, Windows and Mac minimum. -- View this message in context: http://boost.2283326.n4.nabble.com/Communication-between-QThread-and-boost-t... Sent from the Boost - Users mailing list archive at Nabble.com.

The Gui is in Qt and Api is in boost. The Gui is meant to sit on top of Api. One of the functions of Api is to do network level data management, process data in certain ways and communicate with the Gui (ie., bridge Gui with other end of Api). To keep the GUI from freezing Api does it's work in a separate thread. If both Gui and Api had used Qt, communication would have been easier with cross-threaded signal-slot mechanism of Qt. Api emits and returns immediately and vice-versa. So none would be blocked unless explicitly specified (*Qt::BlockingQueuedConnection*). I've been using boost only since a while back as it was required to code new Api in boost. How do i achieve this mechanism in *boost <--> Qt communication*? Api is going to be header+static_library and so Gui and Api will produce single executable. I have to support Linux, Windows and Mac minimum.
You can emulate this behaviour using boost::asio::io_service::post(): in the Api layer make an "active object", whos interface functions just post to the implementation: class your_class { public: do_something() { io_service_.post([=] {do_something_sync();}); } private: do_something_sync() { // heavy processing } };

Thanks Igor. I went through the asio reference and did come across post() (event queue like) and dispatch() (blocking direct call like). So this will it then. Further, since io_service's post seems to invoke queued calls in undefined order (could be sequentially as it does presently but reference says not to depend on it), i used strand's post(). I's always a light boost user (only regex and a few others) due to Qt-heavy projects but now have been going through boost's reference pages and sources for over a couple of weeks and must say what superb piece of architecture and concepts ! btw just curious, why didn't you call do_something_sync() directly in post() instead of through a lambda? -- View this message in context: http://boost.2283326.n4.nabble.com/Communication-between-QThread-and-boost-t... Sent from the Boost - Users mailing list archive at Nabble.com.

btw just curious, why didn't you call do_something_sync() directly in post() instead of through a lambda?
Without lambda I'd have to create a binder: boost::bind(&class_name::do_something_sync, this). It's just a bit more verbose :). But in a real code there's also another point: usually it's preferable to use shared_from_this idiom with async functions, to simplify control over object lifetime. So it would be either { io_.post(bind(&class_name::do_something_sync, shared_from_this())); } or { auto self = shared_from_this(); io_.post([=] { self->do_something_sync(); }); } ...so the bind version already looks less verbose.

On Mon, Feb 11, 2013 at 8:16 AM, ustulation
The Gui is in Qt and Api is in boost. The Gui is meant to sit on top of Api. One of the functions of Api is to do network level data management, process data in certain ways and communicate with the Gui (ie., bridge Gui with other end of Api). To keep the GUI from freezing Api does it's work in a separate thread. If both Gui and Api had used Qt, communication would have been easier with cross-threaded signal-slot mechanism of Qt. Api emits and returns immediately and vice-versa. So none would be blocked unless explicitly specified (*Qt::BlockingQueuedConnection*). I've been using boost only since a while back as it was required to code new Api in boost. How do i achieve this mechanism in *boost <--> Qt communication*? Api is going to be header+static_library and so Gui and Api will produce single executable. I have to support Linux, Windows and Mac minimum.
I'm doing something similar in one of my projects and after trying several ways I finally got to this (TLDR: make Api a black box): 1. totally isolate Api so that there is no way for Qt code to get data inside it without "requests". 2. Allo Api functions should be thread-safe. 3. Api exposes a simple event pump function. Each time the Qt code calls this function, it returns event objects or nothing if nothing changed. 4. In the Qt part, call the Api event pump function as often as possible, using a timer, so that it's always in sync with the Qt thread. 5. Api never exposes functions returning data. It either don't return anything OR return std::future<MyData> or something similar. 6. Each call to Api functions is a request. The result will be provided through events OR using futures or similar constructs. 7. Api can (but is not forced to) use one or more threads inside it's mechanisms. The important thing is to hide from outiside the fact that it do use multi threading or not. Isolate Api totally. This way, each function from the Api is a request to do something, and each event object retuned by the event pump is a signal. Make sure the event objects are copyable and hold data that are copyable: never share data between inside Api and outside it. So far it works for me but I used this architecture for a short time so I'm not sure yet if it's future proof. Hope it helps. Joel Lamotte

On Mon, Feb 11, 2013 at 8:16 AM, ustulation <ustulation@> wrote:
The Gui is in Qt and Api is in boost. The Gui is meant to sit on top of Api. One of the functions of Api is to do network level data management, process data in certain ways and communicate with the Gui (ie., bridge Gui with other end of Api). To keep the GUI from freezing Api does it's work in a separate thread. If both Gui and Api had used Qt, communication would have been easier with cross-threaded signal-slot mechanism of Qt. Api emits and returns immediately and vice-versa. So none would be blocked unless explicitly specified (*Qt::BlockingQueuedConnection*). I've been using boost only since a while back as it was required to code new Api in boost. How do i achieve this mechanism in *boost <--> Qt communication*? Api is going to be header+static_library and so Gui and Api will produce single executable. I have to support Linux, Windows and Mac minimum.
I'm doing something similar in one of my projects and after trying several ways I finally got to this (TLDR: make Api a black box): 1. totally isolate Api so that there is no way for Qt code to get data inside it without "requests". 2. Allo Api functions should be thread-safe. 3. Api exposes a simple event pump function. Each time the Qt code calls this function, it returns event objects or nothing if nothing changed. 4. In the Qt part, call the Api event pump function as often as possible, using a timer, so that it's always in sync with the Qt thread. 5. Api never exposes functions returning data. It either don't return anything OR return std::future<MyData> or something similar. 6. Each call to Api functions is a request. The result will be provided through events OR using futures or similar constructs. 7. Api can (but is not forced to) use one or more threads inside it's mechanisms. The important thing is to hide from outiside the fact that it do use multi threading or not. Isolate Api totally. This way, each function from the Api is a request to do something, and each event object retuned by the event pump is a signal. Make sure the event objects are copyable and hold data that are copyable: never share data between inside Api and outside it. So far it works for me but I used this architecture for a short time so I'm not sure yet if it's future proof. Hope it helps. Joel Lamotte _______________________________________________ Boost-users mailing list Boost-users@.boost http://lists.boost.org/mailman/listinfo.cgi/boost-users Thanks Joel !! Yes Similar stuff here. I used command pattern with collection of boost::any for data exchange. Api maintains a queue which can be filled with pointers to Command Abstract base class which say has p.v.f execute(). Each Concrete command class has an implementation of execute() to make direct call/s to Api's specific function. Ui then has to grab the Api queue and push in a pointer to specific concrete command class. Then use a notifier that wakes the master Api thread that handles queues. Api grabs the mutex, makes a local copy of the queue, releases mutex immediately and dispatches functions. Api talks similarly to Ui. Ui will have it's own interfaces which Api can call and you use another queue there, or if using Qt use signal-slots, thus isolating Api from Ui. But way easier it is to use Qt on both sides :) -- View this message in context: http://boost.2283326.n4.nabble.com/Communication-between-QThread-and-boost-t... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (3)
-
Igor R
-
Klaim - Joël Lamotte
-
ustulation