Project

General

Profile

Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3

Added by Kai Scherrer over 7 years ago

Hi,

we are currently building a web application which is using Qt for its backend. Therefore we are using WQApplication from the wtwithqt-Example with event loop enabled.

So all our Application-Requests are routed through the DispatchThread in wtwithqt which is great for us! Unfortunatly our emits to Wt::WAbstractTableModel from this thread (layoutAboutToBeChanged, layoutChanged) are defered: rendering is not processed until the next event is sent, for example triggered by the user clicking on a widget.

We can workaround this by calling Wt::WApplication::triggerUpdate() right after layoutChanged.emit() but then the rendering is not performed by our DispatchThread anymore, but instead directly by one of webservers working threads, which is causing that some of our Qt-Objects do not perform correct. This is what the call stack looks alike then:

httpd.exe!Wt::WTableView::render(Wt::WFlags<enum Wt::RenderFlag> flags)
httpd.exe!Wt::WCompositeWidget::getSDomChanges(std::vector<Wt::DomElement [...]) Line 518   C++
httpd.exe!Wt::WebRenderer::collectChanges(std::vector<Wt::DomElement *, [...]) Line 1497    C++
httpd.exe!Wt::WebRenderer::collectJS(Wt::WStringStream * js) Line 1621  C++
httpd.exe!Wt::WebRenderer::collectJavaScriptUpdate(Wt::WStringStream & out) Line 1552   C++
httpd.exe!Wt::WebRenderer::collectJavaScript() Line 755 C++
httpd.exe!Wt::WebRenderer::serveJavaScriptUpdate(Wt::WebResponse & response) Line 557   C++
httpd.exe!Wt::WebRenderer::serveResponse(Wt::WebResponse & response) Line 255   C++
httpd.exe!Wt::WebSession::pushUpdates() Line 1807   C++
httpd.exe!Wt::WebSession::Handler::~Handler() Line 919  C++
httpd.exe!Wt::WebController::handleApplicationEvent( [...]) Line 502    C++
httpd.exe!Wt::WIOService::run() Line 181    C++

Do we have to take special precautions to call layoutChanged.emit() from the DisplayThread-Context?


Replies (6)

RE: Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3 - Added by Kai Scherrer over 7 years ago

Hello Koen,

thanks for your reply.

I've just tested with 3.3.4-rc1 but both problems are still there: the emits of layoutChanged are defered and triggerUpdate() performs those emits outside of the DispatchThread-context. Just the line numbers in the callstack have been changed: ;-)

 httpd.exe!Wt::WTableView::render(Wt::WFlags<enum Wt::RenderFlag> flags) Line 797   C++
 httpd.exe!Wt::WCompositeWidget::getSDomChanges(std::vector<Wt::DomElement [...]) Line 543  C++
 httpd.exe!Wt::WebRenderer::collectChanges(std::vector<Wt::DomElement *, [...]) Line 1516   C++
 httpd.exe!Wt::WebRenderer::collectJS(Wt::WStringStream * js) Line 1642 C++
 httpd.exe!Wt::WebRenderer::collectJavaScriptUpdate(Wt::WStringStream & out) Line 1571  C++
 httpd.exe!Wt::WebRenderer::collectJavaScript() Line 764    C++
 httpd.exe!Wt::WebRenderer::serveJavaScriptUpdate(Wt::WebResponse & response) Line 566  C++
 httpd.exe!Wt::WebRenderer::serveResponse(Wt::WebResponse & response) Line 257  C++
 httpd.exe!Wt::WebSession::pushUpdates() Line 1895  C++
 httpd.exe!Wt::WebSession::Handler::~Handler() Line 1003    C++
 httpd.exe!Wt::WebController::handleApplicationEvent(const Wt::ApplicationEvent & event) Line 531   C++
 httpd.exe!Wt::WIOService::run() Line 181   C++

RE: Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3 - Added by Koen Deforche over 7 years ago

Hey,

It sounds like you should be able to create a small test case and could you tgen submit it as a bug? I want this to be fixed for 3.3.4.

Thanks,

Koen

RE: Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3 - Added by Kai Scherrer over 7 years ago

Hi Koen,

sorry, it took me a while to set up a test case, but here it is:

http://www.kaiiv.de/WtThreadingProblem.zip

In this Archive there is the Source for an application object derived from Wt::WQApplication (DemoApplication) and a model derived from Wt::WAbstractTableModel (DemoModel).

I've placed comments all over the code and I hope it is understandable :-)

The essence of the problem is in the method DemoModel::postLayoutChanged() which I quote here:

void DemoModel::postLayoutChanged()
{
        // We are called within the context of Wt::WServer::post() which was placed in DemoModel::rowInserterThreadProc()
        const auto app  = Wt::WApplication::instance();
        assert(app);
        if (app)
        {
                // So here is issue #1: to my understanding emitting layoutChanged is sufficient to
                // update the table view immediately... 
                layoutChanged().emit();

                // ...but it does not happen until the user is doing some action inside the browser, e.g.
                // by clicking on a row.

                // Anyway, if I call tiggerUpdate() the user is getting the model updates in his browser as expected, but 
                // this brings us to issue #2:
                // The resulting update is then not done from within the WQapplication thread context anymore.
                // Watch out for the asserts in columnCount(), rowCount(), data() and headerDate().

                // comment out the next line to see issue #2 in action
                // app->triggerUpdate();
        }
}

Thank's for your support!

Kind regards,

Kai

RE: Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3 - Added by Kai Scherrer over 7 years ago

The source compiles with Visual Studio 2013, but I'm not using any windows stuff, so it will hopefully compile on other platforms with minor modifications, only.

RE: Threading problem in with wtwithqt-Example and Wt::WAbstractTableModel/Wt::WTableView in Wt 3.3.3 - Added by Kai Scherrer over 7 years ago

As you suggested I've created a Ticket for that issue: http://redmine.emweb.be/issues/3735

Attached there is an updated test case which compiles with VS2013 and GCC4.7 (tested with Debian Wheezy)

    (1-6/6)