/* This file is part of Clementine. Copyright 2012, David Sansome Clementine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Clementine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Clementine. If not, see . */ #ifndef CONCURRENTRUN_H #define CONCURRENTRUN_H #include #include #include #include #include /* The aim of ThreadFunctor classes and ConcurrentRun::Run() functions is to complete QtConcurrentRun, which lack support for using a particular QThreadPool, as it always uses QThreadPool::globalInstance(). This is problematic when we do not want to share the same thread pool over all the application, but want to keep the convenient QtConcurrent::run() functor syntax. With ConcurrentRun::Run(), time critical changes can be performed in their own pool, which is not empty by other actions (as it happens when using QtConcurrentRun::run()). ThreadFunctor classes are used to store a functor and its arguments, and Run() functions are used for convenience: to directly create a new ThreadFunctor object and start it. Currently, only functions with zero, one, two or three arguments are supported, but other might be added easily for X arguments by defining a new ThreadFunctorX class (and eventually a second class for handling functions which return void: see existing classes for examples), and add new Run() function. */ /* Base abstract classes ThreadFunctorBase and ThreadFunctor (for void and non-void result): */ template class ThreadFunctorBase : public QFutureInterface, public QRunnable { public: ThreadFunctorBase() {} QFuture Start(QThreadPool* thread_pool) { this->setRunnable(this); this->reportStarted(); Q_ASSERT(thread_pool); QFuture future = this->future(); thread_pool->start(this, 0 /* priority: currently we do not support changing the priority. Might be added later if needed */); return future; } virtual void run() = 0; }; template class ThreadFunctor : public ThreadFunctorBase { public: ThreadFunctor(std::function function, Args... args) : function_(std::bind(function, args...)) { } virtual void run() { this->reportResult(function_()); this->reportFinished(); } private: std::function function_; }; // Partial specialisation for void return type. template class ThreadFunctor : public ThreadFunctorBase { public: ThreadFunctor(std::function function, Args... args) : function_(std::bind(function, args...)) { } virtual void run() { function_(); this->reportFinished(); } private: std::function function_; }; /* Run functions */ namespace ConcurrentRun { // Empty argument form. template QFuture Run( QThreadPool* threadpool, std::function function) { return (new ThreadFunctor(function))->Start(threadpool); } // Function object with arguments form. template QFuture Run( QThreadPool* threadpool, std::function function, const Args&... args) { return (new ThreadFunctor( function, args...))->Start(threadpool); } // Support passing C function pointers instead of function objects. template QFuture Run( QThreadPool* threadpool, ReturnType (*function) (Args...), const Args&... args) { return Run( threadpool, std::function(function), args...); } } #endif // CONCURRENTRUN_H