Project

General

Profile

Actions

Feature #9725

open

Add manual multi-threading support

Added by Loren Burkholder about 2 years ago. Updated about 2 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
02/07/2022
Due date:
% Done:

0%

Estimated time:
1:00 h

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:

  1. Add a function void registerThread(int) or void registerThread(std::thread &) that registers a thread as being associated with the current thread.
  2. Add a function std::thread &createThread(Function &f, Args &...) that passes all arguments to a std::thread. This thread is registered with Wt and then returned.
Actions #1

Updated by Roel Standaert about 2 years ago

Actions #2

Updated by Loren Burkholder about 2 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.

Actions

Also available in: Atom PDF