Git commit 821d76eb051b02cc3561e334e50c020fa812d26a by Michael Leupold. Committed on 10/08/2010 at 10:50. Pushed by vrusu into branch 'ksecretsservice'. Add a new queued job class which will be used as a replacement for AsyncCall and will also help implementing gui jobs. svn path=/trunk/playground/base/ksecretservice/; revision=1161477 A +96 -0 jobqueue.cpp [License: GPL (v2/3)] A +76 -0 jobqueue_p.h [License: GPL (v2/3)] A +119 -0 queuedjob.h [License: GPL (v2/3)] A +7 -0 CMakeLists.txt A +61 -0 jobqueue.h [License: GPL (v2/3)] A +75 -0 queuedjob.cpp [License: GPL (v2/3)] http://commits.kde.org/kdelibs/821d76eb051b02cc3561e334e50c020fa812d26a diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2095d54 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +SET (ksecretservice_lib_SRCS + jobqueue.cpp + queuedjob.cpp +) + +KDE4_ADD_LIBRARY (ksecretservicelib STATIC ${ksecretservice_lib_SRCS}) +TARGET_LINK_LIBRARIES (ksecretservicelib ${QT_QTCORE_LIBRARY}) diff --git a/jobqueue.cpp b/jobqueue.cpp new file mode 100644 index 0000000..5cdee0c --- /dev/null +++ b/jobqueue.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2010, Michael Leupold + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#include "jobqueue.h" +#include "queuedjob.h" +#include "jobqueue_p.h" + +#include + +JobQueuePrivate::JobQueuePrivate() +{ +} + +JobQueuePrivate::~JobQueuePrivate() +{ + // TODO: make sure there's no jobs left running when we go down +} + +void JobQueuePrivate::enqueue(QueuedJob *job, bool inFront) +{ + Q_ASSERT(job); + if (inFront) { + m_jobs.prepend(job); + } else { + m_jobs.enqueue(job); + } + + if (m_currentJob.isNull()) { + QTimer::singleShot(0, this, SLOT(process())); + } +} + +void JobQueuePrivate::process() +{ + // check if already processing + if (!m_currentJob.isNull()) { + return; + } + + // get a job to execute + // as the job queue consists of QPointers, jobs which have been dismissed + // (deleted) are automatically weeded out. + while (m_currentJob.isNull()) { + if (m_jobs.isEmpty()) { + return; + } + m_currentJob = m_jobs.dequeue(); + } + + connect(m_currentJob.data(), SIGNAL(result(QueuedJob*)), + SLOT(jobFinished(QueuedJob*))); +} + +void JobQueuePrivate::jobFinished(QueuedJob *job) +{ + Q_UNUSED(job); + Q_ASSERT(job == m_currentJob); + m_currentJob = 0; + // keep processing if there's more jobs + if (!m_jobs.isEmpty()) { + QTimer::singleShot(0, this, SLOT(process())); + } +} + +JobQueue::JobQueue() : d(new JobQueuePrivate) +{ +} + +JobQueue::~JobQueue() +{ + delete d; +} + +void JobQueue::enqueue(QueuedJob *job, bool inFront) +{ + d->enqueue(job, inFront); +} + +#include "jobqueue_p.moc" diff --git a/jobqueue.h b/jobqueue.h new file mode 100644 index 0000000..9275906 --- /dev/null +++ b/jobqueue.h @@ -0,0 +1,61 @@ +/* + * Copyright 2010, Michael Leupold + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#ifndef JOBQUEUE_H +#define JOBQUEUE_H + +// forward declarations +class QueuedJob; +class JobQueuePrivate; + +/** + * Generic class which is used for queueing objects of class QueuedJob + * and executing them one after another. + * + * This class does intentionally not inherit QObject so it can be inherited + * by other QObject-based classes. + */ +class JobQueue +{ +public: + /** + * Constructor. + */ + JobQueue(); + + /** + * Destructor. + */ + virtual ~JobQueue(); + + /** + * Enqueue a job for processing. + * + * @param job the job to enqueue + * @param inFront true to enqueue the job in front so it is the next + * job to be processed + */ + void enqueue(QueuedJob *job, bool inFront = false); + +private: + JobQueuePrivate *d; +}; + +#endif // JOBQUEUE_H diff --git a/jobqueue_p.h b/jobqueue_p.h new file mode 100644 index 0000000..77f1a79 --- /dev/null +++ b/jobqueue_p.h @@ -0,0 +1,76 @@ +/* + * Copyright 2010, Michael Leupold + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#ifndef JOBQUEUE_P_H +#define JOBQUEUE_P_H + +#include +#include +#include + +// forward declarations +class QueuedJob; + +/** + * Private JobQueue class that implements most of the logic. + */ +class JobQueuePrivate : public QObject +{ + Q_OBJECT + +public: + /** + * Constructor. + */ + JobQueuePrivate(); + + /** + * Destructor. + */ + ~JobQueuePrivate(); + + /** + * Enqueue a job for processing. + * + * @param job the job to enqueue + * @param inFront true to enqueue the job in front so it is the next + * job to be processed + */ + void enqueue(QueuedJob *job, bool inFront); + +private Q_SLOTS: + /** + * Start processing jobs. + */ + void process(); + + /** + * Used to receive result() signals of the current QueuedJob. + * + * @param job the job that sends its result + */ + void jobFinished(QueuedJob *job); + +private: + QQueue > m_jobs; + QPointer m_currentJob; +}; + +#endif // JOBQUEUE_P_H diff --git a/queuedjob.cpp b/queuedjob.cpp new file mode 100644 index 0000000..a6d8828 --- /dev/null +++ b/queuedjob.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2010, Michael Leupold + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#include "queuedjob.h" +#include "jobqueue.h" + +class QueuedJobPrivate +{ +public: + JobQueue *m_queue; + bool m_finished; + bool m_enqueued; +}; + +QueuedJob::QueuedJob(JobQueue *queue) + : d(new QueuedJobPrivate) +{ + Q_ASSERT(queue); + + d->m_queue = queue; + d->m_finished = false; + d->m_enqueued = false; +} + +QueuedJob::~QueuedJob() +{ + delete d; +} + +bool QueuedJob::isImmediate() const +{ + return false; +} + +bool QueuedJob::isFinished() const +{ + return d->m_finished; +} + +void QueuedJob::enqueue(bool inFront) +{ + // if the job has already been finished or enqueued, handle this + // gracefully. + if (d->m_enqueued || d->m_finished) { + return; + } + d->m_queue->enqueue(this, inFront); + d->m_enqueued = true; +} + +void QueuedJob::emitResult() +{ + d->m_finished = true; + emit result(this); + deleteLater(); +} + +#include "queuedjob.moc" diff --git a/queuedjob.h b/queuedjob.h new file mode 100644 index 0000000..b0941b2 --- /dev/null +++ b/queuedjob.h @@ -0,0 +1,119 @@ +/* + * Copyright 2010, Michael Leupold + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#ifndef QUEUEDJOB_H +#define QUEUEDJOB_H + +#include + +// forward declaration +class JobQueue; +class QueuedJobPrivate; + +/** + * Job-class that provides the ability to queue jobs in a JobQueue. + * + * @note Just like KJob, QueuedJob is meant to be used in a fire-and-forget + * way. It's deleting itself when it has finished using deleteLater() + * so the job instance disappears after the next event loop run. + */ +class QueuedJob : public QObject +{ + Q_OBJECT + +public: + /** + * Constructor. + * + * @param queue queue the job will be enqueued into + */ + explicit QueuedJob(JobQueue *queue); + + /** + * Destructor. + */ + virtual ~QueuedJob(); + + /** + * Checks if this call can be made immediately/synchronously. + * + * @return true if the call can be made immediately, false if it needs to + * be queued + * @note The base implementation always returns false, so if your job class + * isn't immediate, you don't have to reimplement this method. + */ + virtual bool isImmediate() const; + + /** + * Check whether this job is finished. + * + * @return true if the job is finished, false else + */ + bool isFinished() const; + + /** + * Enqueue this job into the JobQueue passed in its constructor. + * + * @param inFront true to enqueue the job in front so it is the next job + * to be processed + */ + void enqueue(bool inFront = false); + + /** + * Execute this job synchronously. Implementation of this method should + * not involve an event-loop and it should only be available if the job + * advertised that it can be called immediately. + * + * @note This method may emit the result but it doesn't have to. If it + * doesn't call emitResult() it has to ensure that the object gets + * deleted using deleteLater() by itself. + */ + virtual void exec() = 0; + + /** + * Start the job asynchronously. + * + * When the job is finished, result() is emitted. + */ + virtual void start() = 0; + +protected: + /** + * Emit the result of this job, notifying every object listening that + * it's finished. + */ + void emitResult(); + +Q_SIGNALS: + /** + * Emit the result of this job. + * + * As this signal can't be emitted directly from derived classes, use + * emitResult() to mark the job as finished and emit this signal. + * + * @param job The job that finished (this object) + */ + void result(QueuedJob *job); + +private: + QueuedJobPrivate *d; +}; + +#endif // QUEUEDJOB_H