One other thing - QtConcurrent::run(), QRunnable and invokeMethod() do not provide any standard mid-task cancellation mechanism, which I've found to be a very common need in the context of a client app which is offloading a chunk of heavy work to background threads to avoid UI lag - eg. file operations, parsing. QFuture provides a cancel() method and a QThread's event loop can be quit between processing events but these only work between task execution.
Regards, Rob. On 20 February 2013 16:24, Robert Knight <[email protected]> wrote: > Hello, > > A few thoughts: > > - In general and especially for newcomers, encourage task-orientated > concurrency and avoiding shared state where possible. > This partly about documentation and the examples but also in the kind of > approach that the APIs optimize for. > > - Having had the er, pleasure of debugging a number of concurrency issues > in QThread, ThreadWeaver and other third party libraries over the years, I'd > say there is a very strong case for going with a wrapper around a > well-written and tested existing library where possible. > > A few years back I tended to use the 'create object, move to thread, send > messages' approach to doing background work. > The problem is that it usually isn't explicit enough when reading the code > what data a particular thread can or cannot safety access. > > With cross-thread signals, you have the issue that when you emit a signal, > it isn't immediately clear at that point that you may be > sending data to another thread - depending on who happens to be > listening. If you see that a value is being written into a channel on > the other hand - as you would find in Go or Rust, it is much more explicit > that the value or reference is being passed to another thread for use. > > Regards, > Rob. > > > On 20 February 2013 15:10, Sze Howe Koh <[email protected]> wrote: > >> On 20 February 2013 22:49, André Somers <[email protected]> wrote: >> > Op 20-2-2013 15:45, Sze Howe Koh schreef: >> >> Hi all, >> >> >> >> Some time ago there was some talk about improving Qt's multithreading >> >> API. I'm summarizing them here to stop them from fading into >> >> obscurity, and to see if there's any interest in following them up. >> > There is also a proposal posted here: >> > http://qt-project.org/forums/viewthread/2488 >> > >> > André >> >> André meant http://qt-project.org/forums/viewthread/24884/ :-) >> >> I'd like to add this idea to the mix: Give Qt's low-level API more >> flexibility and consistency. >> >> Currently, Qt's suggestions for multithreading are: >> >> - Subclass a worker QObject and move it to a basic QThread (if an >> event loop is desired) >> - Subclass QThread (if an event loop is not desired) >> - Subclass QRunnable and run it via a QThreadPool (if recycling >> QThreads is desired) >> - Call QtConcurrent::run() (if a parallel function call is desired) >> - Use QtConcurrent's filter-map-reduce API (if high-level container >> processing is desired) >> >> >> Ignoring filter-map-reduce (the only true high-level option here), the >> low-level API looks quite disparate. Furthermore, some features are >> missing: >> >> - The ability to use QRunnable, or make a parallel function call, >> without being tied to a thread pool >> - The ability to emit a signal when a thread finishes with QRunnable >> - The ability to delay a parallel function call >> - The ability to elegantly separate code control and thread logic >> >> >> === PROPOSED NEW METHODS === >> 1) static QThread* QThread::setupSimpleThread(QRunnable *runnable); >> 2) static QThread* QThread::setupSimpleThread(Function func, Args arg, >> ...); >> 3) static QThread* QThread::setupEventLoop(QObject* worker); >> >> 4) void QThreadPool::start(Function func, Args arg, ...); >> 5) bool QThreadPool::tryStart(Function func, Args arg...); >> >> >> === BEHAVIOUR === >> (1) binds a QRunnable to a QThread, which will call the >> QRunnable::run() when start()'ed. >> (2) binds a function and zero or more arguments to a QThread, which >> will call the function when start()'ed. >> (3) moves the worker QObject to the new thread, ready to have its >> slots invoked when the QThread is start()'ed. >> (4) and (5) are similar to (2), but it uses a recyclable thread from a >> QThreadPool and (tries to) start immediately >> >> >> === ADVANTAGES === >> - The missing features mentioned earlier are provided >> - A symmetrical API for using both recycled and unrecycled >> threads(QThreadPool and QThread) >> - A unified, self-documenting API, which clearly distinguishes and >> enforces the 2 different ways to using QThread (both with and without >> an event loop) >> - A way to cleanly separate thread control (QThread) and threaded code >> (QRunnable), thus making it more idiot-proof. Also achieved without >> the huge overhead of the worker-object approach >> >> >> === IMPLEMENTATION === >> (1) The QThread implementation can be similar to QThreadPoolThread, >> except that it doesn't check the number of active threads. >> (2, 4, 5) Ideally, we'd use a variadic template with std::function + >> std::bind behind the scenes. But, since C++98 support is required, I >> guess we'll have to follow QtConcurrent::run()'s approach (multiple >> overloaded templates for different numbers of arguments). >> (3) setupEventLoop() is just a simple wrapper that instantiates a >> basic QThread and calls moveToThread() on the worker, before returning >> the QThread. >> >> >> >> Thoughts? >> >> Regards, >> Sze-Howe >> _______________________________________________ >> Development mailing list >> [email protected] >> http://lists.qt-project.org/mailman/listinfo/development >> > >
_______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
