Feature #9725
openAdd manual multi-threading support
0%
Description
Currently, it is impossible to call any functions relating to a WApplication from another thread (e.g.
Wt::WApplication myAppObject{someWtWEnvironment}};
std::thread t{[&myAppObject] {
myAppObject.refresh();
}};
will crash). One big reason for such crashing is that Wt's internal functions call WApplication::instance()
; if the code is executing in a manually-created std::thread, Wt will not be able to find the WApplication for the thread and will therefore return nullptr
, quickly crashing the app.
I see two ways of fixing this:
- Add a function
void registerThread(int)
orvoid registerThread(std::thread &)
that registers a thread as being associated with the current thread. - Add a function
std::thread &createThread(Function &f, Args &...)
that passes all arguments to astd::thread
. This thread is registered with Wt and then returned.
Updated by Roel Standaert almost 3 years ago
You just have to grab the UpdateLock
: https://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1WApplication_1_1UpdateLock.html
Updated by Loren Burkholder almost 3 years ago
OK, thanks for pointing that out. I'd kinda forgotten about that and I'm pleased to report that it works as expected.
I do think, however, that being able to simply register a thread would be nice. That way, it would be simpler to create sub-threads for the application instead of having to insert pointers in classes in order to keep a copy of the target app. In other words:
class MyClass : public Wt::WContainerWidget
{
public:
MyClass() {}
private:
void doSomething()
{
auto thread = Wt::WApplication::instance()->createThread([this] {
// do some page modification, and then...
const auto app = Wt::WApplication::instance();
if (Wt::WApplication::UpdateLock lock{app}; lock)
app->triggerUpdate();
});
// ...
}
};
is much nicer than:
class MyClass : public Wt::WContainerWidget
{
public:
MyClass() : m_app{Wt::WApplication::instance()} {}
private:
void doSomething()
{
std::thread thread {[this] {
// do some page modification, and then...
if (Wt::WApplication::UpdateLock lock{m_app}; lock)
m_app->triggerUpdate();
}};
// ...
}
Wt::WApplication *m_app;
};
because the first solution doesn't make it the responsibility of the programmer to keep tracking the application pointer.