Move all the things (YES. Move them.)
Also, implemented some basic modlist logic, to be wired up.
This commit is contained in:
180
logic/net/JobQueue.h
Normal file
180
logic/net/JobQueue.h
Normal file
@ -0,0 +1,180 @@
|
||||
#pragma once
|
||||
#include <QtCore>
|
||||
#include "libutil_config.h"
|
||||
|
||||
enum JobStatus
|
||||
{
|
||||
Job_NotStarted,
|
||||
Job_InProgress,
|
||||
Job_Finished,
|
||||
Job_Failed
|
||||
};
|
||||
|
||||
class JobList;
|
||||
|
||||
class LIBUTIL_EXPORT Job : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
explicit Job(): QObject(0){};
|
||||
public:
|
||||
virtual ~Job() {};
|
||||
signals:
|
||||
void finish();
|
||||
void fail();
|
||||
void progress(qint64 current, qint64 total);
|
||||
public slots:
|
||||
virtual void start() = 0;
|
||||
};
|
||||
typedef QSharedPointer<Job> JobPtr;
|
||||
|
||||
/**
|
||||
* A list of jobs, to be processed one by one.
|
||||
*/
|
||||
class LIBUTIL_EXPORT JobList : public QObject
|
||||
{
|
||||
friend class JobListQueue;
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
JobList() : QObject(0)
|
||||
{
|
||||
m_status = Job_NotStarted;
|
||||
current_job_idx = 0;
|
||||
}
|
||||
JobStatus getStatus()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
void add(JobPtr dlable)
|
||||
{
|
||||
if(m_status == Job_NotStarted)
|
||||
m_jobs.append(dlable);
|
||||
//else there's a bug. TODO: catch the bugs
|
||||
}
|
||||
JobPtr getFirstJob()
|
||||
{
|
||||
if(m_jobs.size())
|
||||
return m_jobs[0];
|
||||
else
|
||||
return JobPtr();
|
||||
}
|
||||
void start()
|
||||
{
|
||||
current_job_idx = 0;
|
||||
auto job = m_jobs[current_job_idx];
|
||||
|
||||
connect(job.data(), SIGNAL(progress(qint64,qint64)), SLOT(currentJobProgress(qint64,qint64)));
|
||||
connect(job.data(), SIGNAL(finish()), SLOT(currentJobFinished()));
|
||||
connect(job.data(), SIGNAL(fail()), SLOT(currentJobFailed()));
|
||||
job->start();
|
||||
emit started();
|
||||
}
|
||||
private slots:
|
||||
void currentJobFinished()
|
||||
{
|
||||
if(current_job_idx == m_jobs.size() - 1)
|
||||
{
|
||||
m_status = Job_Finished;
|
||||
emit finished();
|
||||
}
|
||||
else
|
||||
{
|
||||
current_job_idx++;
|
||||
auto job = m_jobs[current_job_idx];
|
||||
connect(job.data(), SIGNAL(progress(qint64,qint64)), SLOT(currentJobProgress(qint64,qint64)));
|
||||
connect(job.data(), SIGNAL(finish()), SLOT(currentJobFinished()));
|
||||
connect(job.data(), SIGNAL(fail()), SLOT(currentJobFailed()));
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
void currentJobFailed()
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
emit failed();
|
||||
}
|
||||
void currentJobProgress(qint64 current, qint64 total)
|
||||
{
|
||||
if(!total)
|
||||
return;
|
||||
|
||||
int total_jobs = m_jobs.size();
|
||||
|
||||
if(!total_jobs)
|
||||
return;
|
||||
|
||||
float job_chunk = 1000.0 / float(total_jobs);
|
||||
float cur = current;
|
||||
float tot = total;
|
||||
float last_chunk = (cur / tot) * job_chunk;
|
||||
|
||||
float list_total = job_chunk * current_job_idx + last_chunk;
|
||||
emit progress(qint64(list_total), 1000LL);
|
||||
}
|
||||
private:
|
||||
QVector<JobPtr> m_jobs;
|
||||
/// The overall status of this job list
|
||||
JobStatus m_status;
|
||||
int current_job_idx;
|
||||
signals:
|
||||
void progress(qint64 current, qint64 total);
|
||||
void started();
|
||||
void finished();
|
||||
void failed();
|
||||
};
|
||||
typedef QSharedPointer<JobList> JobListPtr;
|
||||
|
||||
|
||||
/**
|
||||
* A queue of job lists! The job lists fail or finish as units.
|
||||
*/
|
||||
class LIBUTIL_EXPORT JobListQueue : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobListQueue(QObject *p = 0):
|
||||
QObject(p),
|
||||
currentIndex(0),
|
||||
is_running(false){}
|
||||
|
||||
void enqueue(JobListPtr job)
|
||||
{
|
||||
jobs.enqueue(job);
|
||||
|
||||
// finish or fail, we should catch that and start the next one
|
||||
connect(job.data(),SIGNAL(finished()), SLOT(startNextJob()));
|
||||
connect(job.data(),SIGNAL(failed()), SLOT(startNextJob()));
|
||||
|
||||
if(!is_running)
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(startNextJob()));
|
||||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void startNextJob()
|
||||
{
|
||||
if (jobs.isEmpty())
|
||||
{
|
||||
currentJobList.clear();
|
||||
currentIndex = 0;
|
||||
is_running = false;
|
||||
emit finishedAllJobs();
|
||||
return;
|
||||
}
|
||||
|
||||
currentJobList = jobs.dequeue();
|
||||
is_running = true;
|
||||
currentIndex = 0;
|
||||
currentJobList->start();
|
||||
}
|
||||
|
||||
signals:
|
||||
void finishedAllJobs();
|
||||
|
||||
private:
|
||||
JobListPtr currentJobList;
|
||||
QQueue<JobListPtr> jobs;
|
||||
unsigned currentIndex;
|
||||
bool is_running;
|
||||
};
|
Reference in New Issue
Block a user