Make variadic version of ConcurrentRun::Run()

This commit is contained in:
John Maguire 2012-11-21 16:03:50 +01:00
parent 3b935e89da
commit 1fd0515168
2 changed files with 55 additions and 240 deletions

View File

@ -18,10 +18,9 @@
#ifndef CONCURRENTRUN_H
#define CONCURRENTRUN_H
#include <tr1/functional>
#include <functional>
#include <boost/type_traits.hpp>
#include <boost/utility.hpp>
#include <boost/bind.hpp>
#include <QFuture>
#include <QRunnable>
@ -74,217 +73,39 @@ class ThreadFunctorBase : public QFutureInterface<ReturnType>, public QRunnable
virtual void run() = 0;
};
// Base implemenation for functions having a result to be returned
template<typename ReturnType, class Enabled = void>
template <typename ReturnType, typename... Args>
class ThreadFunctor : public ThreadFunctorBase<ReturnType> {
public:
ThreadFunctor() {}
ThreadFunctor(std::function<ReturnType (Args...)> function,
Args... args)
: function_(std::bind(function, args...)) {
}
virtual void run() = 0;
void End() {
this->reportResult(result_);
virtual void run() {
this->reportResult(function_());
this->reportFinished();
}
protected:
ReturnType result_;
private:
std::function<ReturnType()> function_;
};
// Base implementation for functions with void result
template<typename ReturnType>
class ThreadFunctor<ReturnType, typename boost::enable_if<boost::is_void<ReturnType> >::type>
: public ThreadFunctorBase<ReturnType> {
// Partial specialisation for void return type.
template <typename... Args>
class ThreadFunctor <void, Args...> : public ThreadFunctorBase<void> {
public:
ThreadFunctor() {}
ThreadFunctor(std::function<void (Args...)> function,
Args... args)
: function_(std::bind(function, args...)) {
}
virtual void run() = 0;
void End() {
virtual void run() {
function_();
this->reportFinished();
}
};
/*
ThreadFunctor with no arguments:
*/
// Non-void result
template<typename ReturnType, class Enabled = void>
class ThreadFunctor0 : public ThreadFunctor<ReturnType> {
public:
ThreadFunctor0(std::tr1::function<ReturnType ()> function)
: function_(function)
{ }
void run() {
this->result_ = function_();
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType ()> function_;
};
// Void result
template<typename ReturnType>
class ThreadFunctor0<ReturnType, typename boost::enable_if<boost::is_void<ReturnType> >::type>
: public ThreadFunctor<ReturnType> {
public:
ThreadFunctor0(std::tr1::function<ReturnType ()> function)
: function_(function)
{ }
void run() {
function_();
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType ()> function_;
};
/*
ThreadFunctor with one argument:
*/
// Non-void result
template<typename ReturnType, typename Arg, class Enabled = void>
class ThreadFunctor1 : public ThreadFunctor<ReturnType> {
public:
ThreadFunctor1(std::tr1::function<ReturnType (Arg)> function,
const Arg& arg)
: function_(function),
arg_(arg)
{ }
void run() {
this->result_ = function_(arg_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg)> function_;
Arg arg_;
};
// Void result
template<typename ReturnType, typename Arg>
class ThreadFunctor1<ReturnType, Arg, typename boost::enable_if<boost::is_void<ReturnType> >::type>
: public ThreadFunctor<ReturnType> {
public:
ThreadFunctor1(std::tr1::function<ReturnType (Arg)> function,
const Arg& arg)
: function_(function),
arg_(arg)
{ }
void run() {
function_(arg_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg)> function_;
Arg arg_;
};
/*
ThreadFunctor with two arguments:
*/
// Non-void result
template<typename ReturnType, typename Arg1, typename Arg2, class Enabled = void>
class ThreadFunctor2 : public ThreadFunctor<ReturnType> {
public:
ThreadFunctor2(std::tr1::function<ReturnType (Arg1, Arg2)> function,
const Arg1& arg1, const Arg2& arg2)
: function_(function),
arg1_(arg1),
arg2_(arg2)
{ }
void run() {
this->result_ = function_(arg1_, arg2_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg1, Arg2)> function_;
Arg1 arg1_;
Arg2 arg2_;
};
// Void result
template<typename ReturnType, typename Arg1, typename Arg2>
class ThreadFunctor2<ReturnType, Arg1, Arg2, typename boost::enable_if<boost::is_void<ReturnType> >::type>
: public ThreadFunctor<ReturnType> {
public:
ThreadFunctor2(std::tr1::function<ReturnType (Arg1, Arg2)> function,
const Arg1& arg1, const Arg2& arg2)
: function_(function),
arg1_(arg1),
arg2_(arg2)
{ }
void run() {
function_(arg1_, arg2_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg1, Arg2)> function_;
Arg1 arg1_;
Arg2 arg2_;
};
/*
ThreadFunctor with three arguments:
*/
// Non-void result
template<typename ReturnType, typename Arg1, typename Arg2, typename Arg3, class Enabled = void>
class ThreadFunctor3 : public ThreadFunctor<ReturnType> {
public:
ThreadFunctor3(std::tr1::function<ReturnType (Arg1, Arg2, Arg3)> function,
const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
: function_(function),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{ }
void run() {
this->result_ = function_(arg1_, arg2_, arg3_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg1, Arg2, Arg3)> function_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
};
// Void result
template<typename ReturnType, typename Arg1, typename Arg2, typename Arg3>
class ThreadFunctor3<ReturnType, Arg1, Arg2, Arg3, typename boost::enable_if<boost::is_void<ReturnType> >::type>
: public ThreadFunctor<ReturnType> {
public:
ThreadFunctor3(std::tr1::function<ReturnType (Arg1, Arg2, Arg3)> function,
const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
: function_(function),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{ }
void run() {
function_(arg1_, arg2_, arg3_);
ThreadFunctor<ReturnType>::End();
}
private:
std::tr1::function<ReturnType (Arg1, Arg2, Arg3)> function_;
Arg1 arg1_;
Arg2 arg2_;
Arg3 arg3_;
private:
std::function<void()> function_;
};
@ -293,39 +114,32 @@ private:
*/
namespace ConcurrentRun {
template<typename ReturnType>
// Empty argument form.
template <typename ReturnType>
QFuture<ReturnType> Run(
QThreadPool* threadpool,
std::tr1::function<ReturnType ()> function) {
return (new ThreadFunctor0<ReturnType>(function))->Start(threadpool);
std::function<ReturnType ()> function) {
return (new ThreadFunctor<ReturnType>(function))->Start(threadpool);
}
template<typename ReturnType, typename Arg>
// Function object with arguments form.
template <typename ReturnType, typename... Args>
QFuture<ReturnType> Run(
QThreadPool* threadpool,
std::tr1::function<ReturnType (Arg)> function,
const Arg& arg) {
return (new ThreadFunctor1<ReturnType, Arg>(function, arg))->Start(threadpool);
std::function<ReturnType (Args...)> function,
const Args&... args) {
return (new ThreadFunctor<ReturnType, Args...>(
function, args...))->Start(threadpool);
}
template<typename ReturnType, typename Arg1, typename Arg2>
// Support passing C function pointers instead of function objects.
template <typename ReturnType, typename... Args>
QFuture<ReturnType> Run(
QThreadPool* threadpool,
std::tr1::function<ReturnType (Arg1, Arg2)> function,
const Arg1& arg1, const Arg2& arg2) {
return (new ThreadFunctor2<ReturnType, Arg1, Arg2>(function, arg1, arg2))->Start(threadpool);
}
template<typename ReturnType, typename Arg1, typename Arg2, typename Arg3>
QFuture<ReturnType> Run(
QThreadPool* threadpool,
std::tr1::function<ReturnType (Arg1, Arg2, Arg3)> function,
const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) {
return (new ThreadFunctor3<ReturnType, Arg1, Arg2, Arg3>(function, arg1, arg2, arg3))->Start(threadpool);
ReturnType (*function) (Args...),
const Args&... args) {
return Run(
threadpool, std::function<ReturnType (Args...)>(function), args...);
}
}

View File

@ -15,8 +15,22 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "songloader.h"
#include <functional>
#include <QBuffer>
#include <QDirIterator>
#include <QFileInfo>
#include <QTimer>
#include <QUrl>
#include <QtDebug>
#ifdef HAVE_AUDIOCD
# include <gst/cdda/gstcddabasesrc.h>
#endif
#include "config.h"
#include "core/concurrentrun.h"
#include "core/logging.h"
#include "core/song.h"
@ -34,19 +48,6 @@
#include "podcasts/podcastservice.h"
#include "podcasts/podcasturlloader.h"
#include <QBuffer>
#include <QDirIterator>
#include <QFileInfo>
#include <QTimer>
#include <QUrl>
#include <QtDebug>
#include <boost/bind.hpp>
#ifdef HAVE_AUDIOCD
# include <gst/cdda/gstcddabasesrc.h>
#endif
QSet<QString> SongLoader::sRawUriSchemes;
const int SongLoader::kDefaultTimeout = 5000;
@ -230,7 +231,7 @@ SongLoader::Result SongLoader::LoadLocal(const QString& filename, bool block,
if (QFileInfo(filename).isDir()) {
if (!block) {
ConcurrentRun::Run<void>(&thread_pool_,
boost::bind(&SongLoader::LoadLocalDirectoryAndEmit, this, filename));
std::bind(&SongLoader::LoadLocalDirectoryAndEmit, this, filename));
return WillLoadAsync;
} else {
LoadLocalDirectory(filename);
@ -263,7 +264,7 @@ SongLoader::Result SongLoader::LoadLocal(const QString& filename, bool block,
// It's a playlist!
if (!block) {
ConcurrentRun::Run<void>(&thread_pool_,
boost::bind(&SongLoader::LoadPlaylistAndEmit, this, parser, filename));
std::bind(&SongLoader::LoadPlaylistAndEmit, this, parser, filename));
return WillLoadAsync;
} else {
LoadPlaylist(parser, filename);