diff options
author | Andrew Christian <andrew.christian@nokia.com> | 2012-03-19 14:58:30 -0400 |
---|---|---|
committer | Andrew Christian <andrew.christian@nokia.com> | 2012-03-21 11:50:43 +0100 |
commit | b429341fc681860b5ef582fe0e1101d522d830e9 (patch) | |
tree | 9c09a23e9dd75c0f94de1328085e44b2aa22ca63 | |
parent | 60f77b663fe83ce796bdd68813e506585c161fd7 (diff) |
Added idle CPU resource allocation for prelaunching
* ProcessBackendFactories indicate a need for extra
cycles by setting idleCpuRequest property.
* PrelaunchBackendFactory requests this whenever
it wants to prelaunch a backend.
* ProcessBackendManager aggregates idleCpuRequest
properties and passes combined request to IdleDelegate.
* IdleDelegate periodically sends idleCpuAvailable()
signal to first available factory with outstanding
request.
* The default IdleDelegate is set to TimeoutIdleDelegate
which distributes idleCpuAvailable() signals at
regular intervals. This is close to the old prelaunch
logic, but now centralized and replaceable.
* The CpuIdleDelegate measures system load (Linux & Mac)
and distributes idleCpuAvailable() signals when the
system load falls below a set level
Change-Id: I1ce273b2797ae0f0477dd80ae7bc2c8e3496901e
Reviewed-by: Andrew Christian <andrew.christian@nokia.com>
-rw-r--r-- | src/core/core-lib.pri | 6 | ||||
-rw-r--r-- | src/core/cpuidledelegate.cpp | 258 | ||||
-rw-r--r-- | src/core/cpuidledelegate.h | 87 | ||||
-rw-r--r-- | src/core/idledelegate.cpp | 79 | ||||
-rw-r--r-- | src/core/idledelegate.h | 64 | ||||
-rw-r--r-- | src/core/prelaunchprocessbackendfactory.cpp | 72 | ||||
-rw-r--r-- | src/core/prelaunchprocessbackendfactory.h | 11 | ||||
-rw-r--r-- | src/core/processbackendfactory.cpp | 57 | ||||
-rw-r--r-- | src/core/processbackendfactory.h | 8 | ||||
-rw-r--r-- | src/core/processbackendmanager.cpp | 149 | ||||
-rw-r--r-- | src/core/processbackendmanager.h | 20 | ||||
-rw-r--r-- | src/core/timeoutidledelegate.cpp | 123 | ||||
-rw-r--r-- | src/core/timeoutidledelegate.h | 72 | ||||
-rw-r--r-- | tests/auto/processmanager/tst_processmanager.cpp | 7 | ||||
-rw-r--r-- | tests/manual/cpuload/.gitignore | 1 | ||||
-rw-r--r-- | tests/manual/cpuload/cpuload.pro | 7 | ||||
-rw-r--r-- | tests/manual/cpuload/tst_cpuload.cpp | 96 |
17 files changed, 1040 insertions, 77 deletions
diff --git a/src/core/core-lib.pri b/src/core/core-lib.pri index 42e7f69..358192d 100644 --- a/src/core/core-lib.pri +++ b/src/core/core-lib.pri @@ -12,6 +12,9 @@ PUBLIC_HEADERS += \ $$PWD/matchdelegate.h \ $$PWD/rewritedelegate.h \ $$PWD/gdbrewritedelegate.h \ + $$PWD/idledelegate.h \ + $$PWD/timeoutidledelegate.h \ + $$PWD/cpuidledelegate.h \ $$PWD/infomatchdelegate.h \ $$PWD/keymatchdelegate.h \ $$PWD/processinfo.h \ @@ -48,6 +51,9 @@ SOURCES += \ $$PWD/matchdelegate.cpp \ $$PWD/rewritedelegate.cpp \ $$PWD/gdbrewritedelegate.cpp \ + $$PWD/idledelegate.cpp \ + $$PWD/timeoutidledelegate.cpp \ + $$PWD/cpuidledelegate.cpp \ $$PWD/infomatchdelegate.cpp \ $$PWD/keymatchdelegate.cpp \ $$PWD/processinfo.cpp \ diff --git a/src/core/cpuidledelegate.cpp b/src/core/cpuidledelegate.cpp new file mode 100644 index 0000000..46dfe1a --- /dev/null +++ b/src/core/cpuidledelegate.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QFile> + +#ifdef Q_OS_MAC +#include <mach/mach.h> +#include <mach/mach_host.h> +#include <mach/processor_info.h> +#endif + +#include "cpuidledelegate.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +const int kIdleTimerInterval = 1000; +const double kDefaultLoadThreshold = 0.4; + +/*! + \class CpuIdleDelegate + \brief The CpuIdleDelegate class generates a periodic cpu. + + The CpuIdleDelegate class generates a periodic cpu for + creation of idle resources. When idle CPU resources are requested + it checks the system load level approximately once per second. When + the load level is below the threshold set by \l{loadThreshold}, the + idleCpuAvailable() signal will be omitted. +*/ + +/*! + \property CpuIdleDelegate::idleInterval + \brief Time in milliseconds before a new idle CPU request will be fulfilled + */ + +/*! + \property CpuIdleDelegate::loadThreshold + \brief Load level we need to be under to generate idle CPU requests. + + This value is a double that ranges from 0.0 to 1.0. A value greater + than or equal to 1.0 guarantees that \l{idleCpuAvailable()} signals + will always be emitted. A value less than 0.0 blocks all \l{idleCpuAvailable()} + signals. + */ + + +/*! + Construct a CpuIdleDelegate with an optional \a parent. +*/ + +CpuIdleDelegate::CpuIdleDelegate(QObject *parent) + : IdleDelegate(parent) + , m_load(1.0) + , m_loadThreshold(kDefaultLoadThreshold) + , m_total(0) + , m_idle(0) +{ + connect(&m_timer, SIGNAL(timeout()), SLOT(timeout())); + m_timer.setInterval(kIdleTimerInterval); +} + +/*! + \fn void CpuIdleDelegate::requestIdleCpu(bool request) + + Turn on or off idle requests based on \a request + You must override this function in a subclass. +*/ + +void CpuIdleDelegate::requestIdleCpu(bool request) +{ + if (request != m_timer.isActive()) { + if (request) { + updateStats(true); + m_timer.start(); + } + else { + m_timer.stop(); + } + } +} + +/*! + \internal + */ + +double CpuIdleDelegate::updateStats(bool reset) +{ + int idle = 0; + int total = 0; + + m_load = 1.0; // Always reset to max in case of error + +#if defined(Q_OS_LINUX) + QList<QByteArray> stats; + QFile file(QStringLiteral("/proc/stat")); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QByteArray line = file.readLine(); + int offset = 0; + while (offset < line.size() && !isdigit(line.at(offset))) + offset++; + if (offset < line.size()) + stats = line.mid(offset).split(' '); + } + if (stats.size() < 5) + qFatal("Unable to read /proc/stat file"); + + idle = stats.at(3).toInt(); + for (int i = 1 ; i < stats.size() ; i++) + total += stats.at(i).toInt(); + +#elif defined(Q_OS_MAC) + natural_t n_cpus; + processor_info_t pinfo; + mach_msg_type_number_t msg_count; + kern_return_t status = host_processor_info(mach_host_self(), + PROCESSOR_CPU_LOAD_INFO, + &n_cpus, + (processor_info_array_t *)&pinfo, + &msg_count); + if (status != KERN_SUCCESS) + qFatal("Unable to read host processor info"); + + for (unsigned int cpu = 0 ; cpu < n_cpus ; cpu++) { + processor_info_t p = pinfo + (CPU_STATE_MAX * cpu); + total += p[CPU_STATE_USER] + p[CPU_STATE_SYSTEM] + + p[CPU_STATE_NICE] + p[CPU_STATE_IDLE]; + idle += p[CPU_STATE_IDLE]; + } + vm_deallocate(mach_task_self(), + (vm_address_t)pinfo, + (vm_size_t)sizeof(*pinfo) * msg_count); +#endif + if (!reset && total > m_total) + m_load = 1.0 - ((float) (idle - m_idle)) / (total - m_total); + + m_total = total; + m_idle = idle; + return m_load; +} + +/*! + \internal + */ + +void CpuIdleDelegate::timeout() +{ + if (updateStats(false) <= m_loadThreshold) + emit idleCpuAvailable(); + emit loadUpdate(m_load); +} + +/*! + Return the current launch interval in milliseconds + */ + +int CpuIdleDelegate::idleInterval() const +{ + return m_timer.interval(); +} + +/*! + Set the current idle interval to \a interval milliseconds +*/ + +void CpuIdleDelegate::setIdleInterval(int interval) +{ + if (m_timer.interval() != interval) { + bool active = m_timer.isActive(); + m_timer.stop(); + m_timer.setInterval(interval); + if (active) + m_timer.start(); + emit idleIntervalChanged(); + } +} + +/*! + Return the current load threshold as a number from 0.0 to 1.0 + */ + +double CpuIdleDelegate::loadThreshold() const +{ + return m_loadThreshold; +} + +/*! + Set the current load threshold to \a threshold milliseconds +*/ + +void CpuIdleDelegate::setLoadThreshold(double threshold) +{ + if (m_loadThreshold != threshold) { + m_loadThreshold = threshold; + emit loadThresholdChanged(); + } +} + +/*! + \fn void CpuIdleDelegate::idleCpuAvailable() + Signal emitted periodically when idle CPU resources are available. +*/ + +/*! + \fn void CpuIdleDelegate::idleIntervalChanged() + This signal is emitted when the idleInterval is changed. + */ + +/*! + \fn void CpuIdleDelegate::loadThresholdChanged() + This signal is emitted when the loadThreshold is changed. + */ + +/*! + \fn void CpuIdleDelegate::loadUpdate(double load) + This signal is emitted when the load is read. It mainly + serves as a debugging signal. The \a load value will + range between 0.0 and 1.0 + */ + + +#include "moc_cpuidledelegate.cpp" + +QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/cpuidledelegate.h b/src/core/cpuidledelegate.h new file mode 100644 index 0000000..63b665d --- /dev/null +++ b/src/core/cpuidledelegate.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CPU_IDLE_DELEGATE_H +#define CPU_IDLE_DELEGATE_H + +#include <QTimer> +#include "idledelegate.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +class ProcessInfo; + +class Q_ADDON_PROCESSMANAGER_EXPORT CpuIdleDelegate : public IdleDelegate +{ + Q_OBJECT + Q_PROPERTY(int idleInterval READ idleInterval WRITE setIdleInterval NOTIFY idleIntervalChanged) + Q_PROPERTY(int loadThreshold READ loadThreshold WRITE setLoadThreshold NOTIFY loadThresholdChanged) + +public: + explicit CpuIdleDelegate(QObject *parent = 0); + virtual void requestIdleCpu(bool request); + + int idleInterval() const; + void setIdleInterval(int interval); + + double loadThreshold() const; + void setLoadThreshold(double threshold); + +signals: + void idleCpuAvailable(); + void idleIntervalChanged(); + void loadThresholdChanged(); + void loadUpdate(double); + +private slots: + void timeout(); + +private: + double updateStats(bool); + +private: + Q_DISABLE_COPY(CpuIdleDelegate); + QTimer m_timer; + double m_load, m_loadThreshold; + int m_total, m_idle; +}; + +QT_END_NAMESPACE_PROCESSMANAGER + +#endif // CPU_IDLE_DELEGATE_H diff --git a/src/core/idledelegate.cpp b/src/core/idledelegate.cpp new file mode 100644 index 0000000..a28441a --- /dev/null +++ b/src/core/idledelegate.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "idledelegate.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +/*! + \class IdleDelegate + \brief The IdleDelegate class is a virtual class for gathering idle CPU cycles + + You must subclass this class to do anything useful. + + The IdleDelegate is turned on and off by the \l{requestIdleCpu()} function. + The IdleDelegate should emit the \l{idleCpuAvailable()} signal approximately + once per second when it is turned on. +*/ + +/*! + Construct a IdleDelegate with an optional \a parent. +*/ + +IdleDelegate::IdleDelegate(QObject *parent) + : QObject(parent) +{ +} + +/*! + \fn void IdleDelegate::requestIdleCpu(bool request) + + Turn on or off idle requests based on \a request + You must override this function in a subclass. +*/ + +/*! + \fn void IdleDelegate::idleCpuAvailable() + + Signal emitted periodically when idle CPU resources are available. +*/ + +#include "moc_idledelegate.cpp" + +QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/idledelegate.h b/src/core/idledelegate.h new file mode 100644 index 0000000..d58bf83 --- /dev/null +++ b/src/core/idledelegate.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef IDLE_DELEGATE_H +#define IDLE_DELEGATE_H + +#include <QObject> +#include "processmanager-global.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +class Q_ADDON_PROCESSMANAGER_EXPORT IdleDelegate : public QObject +{ + Q_OBJECT +public: + explicit IdleDelegate(QObject *parent = 0); + virtual void requestIdleCpu(bool request) = 0; + +signals: + void idleCpuAvailable(); + +private: + Q_DISABLE_COPY(IdleDelegate); +}; + +QT_END_NAMESPACE_PROCESSMANAGER + +#endif // IDLE_DELEGATE_H diff --git a/src/core/prelaunchprocessbackendfactory.cpp b/src/core/prelaunchprocessbackendfactory.cpp index 97df879..eb64464 100644 --- a/src/core/prelaunchprocessbackendfactory.cpp +++ b/src/core/prelaunchprocessbackendfactory.cpp @@ -45,8 +45,6 @@ QT_BEGIN_NAMESPACE_PROCESSMANAGER -const int kPrelaunchTimerInterval = 1000; - /*! \class PrelaunchProcessBackendFactory \brief The PrelaunchProcessBackendFactory class creates PrelaunchProcessBackend objects @@ -56,11 +54,6 @@ const int kPrelaunchTimerInterval = 1000; */ /*! - \property PrelaunchProcessBackendFactory::launchInterval - \brief Time in milliseconds before a new prelaunch backend will be started - */ - -/*! \property PrelaunchProcessBackendFactory::processInfo \brief ProcessInfo record used to create the prelaunched process */ @@ -85,9 +78,6 @@ PrelaunchProcessBackendFactory::PrelaunchProcessBackendFactory(QObject *parent) , m_info(NULL) , m_prelaunchEnabled(true) { - connect(&m_timer, SIGNAL(timeout()), SLOT(timeout())); - m_timer.setSingleShot(true); - m_timer.setInterval(kPrelaunchTimerInterval); } /*! @@ -162,31 +152,6 @@ ProcessInfo *PrelaunchProcessBackendFactory::processInfo() const } /*! - Return the current launch interval in milliseconds - */ - -int PrelaunchProcessBackendFactory::launchInterval() const -{ - return m_timer.interval(); -} - -/*! - Set the current launch interval to \a interval milliseconds -*/ - -void PrelaunchProcessBackendFactory::setLaunchInterval(int interval) -{ - if (m_timer.interval() != interval) { - bool active = m_timer.isActive(); - m_timer.stop(); - m_timer.setInterval(interval); - if (active) - startPrelaunchTimer(); - emit launchIntervalChanged(); - } -} - -/*! Returns whether prelaunching is enabled for this factory. */ bool PrelaunchProcessBackendFactory::prelaunchEnabled() const @@ -199,7 +164,7 @@ void PrelaunchProcessBackendFactory::setPrelaunchEnabled(bool value) if (m_prelaunchEnabled != value) { m_prelaunchEnabled = value; if (!m_prelaunchEnabled) { - m_timer.stop(); + setIdleCpuRequest(false); if (m_prelaunch) { m_prelaunch->deleteLater(); m_prelaunch = NULL; @@ -226,7 +191,7 @@ bool PrelaunchProcessBackendFactory::hasPrelaunchedProcess() const void PrelaunchProcessBackendFactory::handleMemoryRestrictionChange() { if (m_memoryRestricted) { - m_timer.stop(); + setIdleCpuRequest(false); if (m_prelaunch) { delete m_prelaunch; // This will kill the child process as well m_prelaunch = NULL; @@ -247,22 +212,21 @@ PrelaunchProcessBackend *PrelaunchProcessBackendFactory::prelaunchProcessBackend /*! Launch a new prelaunched process backend. - In the future, it would be useful if the launch didn't require a timeout. */ -void PrelaunchProcessBackendFactory::timeout() +void PrelaunchProcessBackendFactory::idleCpuAvailable() { - Q_ASSERT(m_prelaunch == NULL); - Q_ASSERT(!m_memoryRestricted); - Q_ASSERT(m_info); - - m_prelaunch = new PrelaunchProcessBackend(*m_info, this); - connect(m_prelaunch, SIGNAL(finished(int,QProcess::ExitStatus)), - SLOT(prelaunchFinished(int,QProcess::ExitStatus))); - connect(m_prelaunch, SIGNAL(error(QProcess::ProcessError)), - SLOT(prelaunchError(QProcess::ProcessError))); - m_prelaunch->prestart(); - emit processPrelaunched(); + if (!m_prelaunch && !m_memoryRestricted && m_info) { + setIdleCpuRequest(false); // Might delay this until the prelaunch is done.... + + m_prelaunch = new PrelaunchProcessBackend(*m_info, this); + connect(m_prelaunch, SIGNAL(finished(int,QProcess::ExitStatus)), + SLOT(prelaunchFinished(int,QProcess::ExitStatus))); + connect(m_prelaunch, SIGNAL(error(QProcess::ProcessError)), + SLOT(prelaunchError(QProcess::ProcessError))); + m_prelaunch->prestart(); + emit processPrelaunched(); + } } /*! @@ -309,7 +273,7 @@ void PrelaunchProcessBackendFactory::prelaunchError(QProcess::ProcessError err) void PrelaunchProcessBackendFactory::startPrelaunchTimer() { if (m_prelaunchEnabled) - m_timer.start(); + setIdleCpuRequest(true); } /*! @@ -333,7 +297,7 @@ void PrelaunchProcessBackendFactory::setProcessInfo(ProcessInfo *processInfo) } startPrelaunchTimer(); } else { - m_timer.stop(); + setIdleCpuRequest(false); } emit processInfoChanged(); } @@ -349,10 +313,6 @@ void PrelaunchProcessBackendFactory::setProcessInfo(ProcessInfo& processInfo) /*! - \fn void PrelaunchProcessBackendFactory::launchIntervalChanged() - This signal is emitted when the launchInterval is changed. - */ -/*! \fn void PrelaunchProcessBackendFactory::processInfoChanged() This signal is emitted when the internal ProcessInfo record is changed. diff --git a/src/core/prelaunchprocessbackendfactory.h b/src/core/prelaunchprocessbackendfactory.h index 66c9923..4a5c0b5 100644 --- a/src/core/prelaunchprocessbackendfactory.h +++ b/src/core/prelaunchprocessbackendfactory.h @@ -42,7 +42,6 @@ #include "processbackendfactory.h" #include "processmanager-global.h" -#include <QTimer> QT_BEGIN_NAMESPACE_PROCESSMANAGER @@ -52,7 +51,6 @@ class PrelaunchProcessBackend; class Q_ADDON_PROCESSMANAGER_EXPORT PrelaunchProcessBackendFactory : public ProcessBackendFactory { Q_OBJECT - Q_PROPERTY(int launchInterval READ launchInterval WRITE setLaunchInterval NOTIFY launchIntervalChanged) Q_PROPERTY(ProcessInfo* processInfo READ processInfo WRITE setProcessInfo NOTIFY processInfoChanged) Q_PROPERTY(bool prelaunchEnabled READ prelaunchEnabled WRITE setPrelaunchEnabled NOTIFY prelaunchEnabledChanged) @@ -69,16 +67,12 @@ public: void setProcessInfo(ProcessInfo *processInfo); void setProcessInfo(ProcessInfo& processInfo); - int launchInterval() const; - void setLaunchInterval(int interval); - bool prelaunchEnabled() const; void setPrelaunchEnabled(bool value); bool hasPrelaunchedProcess() const; signals: - void launchIntervalChanged(); void processInfoChanged(); void prelaunchEnabledChanged(); void processPrelaunched(); @@ -87,8 +81,10 @@ protected: virtual void handleMemoryRestrictionChange(); PrelaunchProcessBackend *prelaunchProcessBackend() const; +protected slots: + virtual void idleCpuAvailable(); + private slots: - void timeout(); void prelaunchFinished(int, QProcess::ExitStatus); void prelaunchError(QProcess::ProcessError); @@ -98,7 +94,6 @@ private: private: PrelaunchProcessBackend *m_prelaunch; ProcessInfo *m_info; - QTimer m_timer; bool m_prelaunchEnabled; }; diff --git a/src/core/processbackendfactory.cpp b/src/core/processbackendfactory.cpp index b676789..17be8d5 100644 --- a/src/core/processbackendfactory.cpp +++ b/src/core/processbackendfactory.cpp @@ -41,6 +41,8 @@ #include "matchdelegate.h" #include "rewritedelegate.h" +#include <QDebug> + QT_BEGIN_NAMESPACE_PROCESSMANAGER /*! @@ -61,6 +63,11 @@ QT_BEGIN_NAMESPACE_PROCESSMANAGER */ /*! + \property ProcessBackendFactory::idleCpuRequest + \brief A boolean value indicating that this factory would like idle CPU cycles +*/ + +/*! Construct a ProcessBackendFactory with an optional \a parent. */ @@ -69,6 +76,7 @@ ProcessBackendFactory::ProcessBackendFactory(QObject *parent) , m_matchDelegate(NULL) , m_rewriteDelegate(NULL) , m_memoryRestricted(false) + , m_idleCpuRequest(false) { } @@ -87,9 +95,9 @@ ProcessBackendFactory::~ProcessBackendFactory() void ProcessBackendFactory::setMemoryRestricted(bool memoryRestricted) { - if (memoryRestricted != m_memoryRestricted) { - m_memoryRestricted = memoryRestricted; - handleMemoryRestrictionChange(); + if (m_memoryRestricted != memoryRestricted) { + m_memoryRestricted = memoryRestricted; + handleMemoryRestrictionChange(); } } @@ -132,7 +140,8 @@ void ProcessBackendFactory::setMatchDelegate(MatchDelegate *matchDelegate) if (m_matchDelegate) delete m_matchDelegate; m_matchDelegate = matchDelegate; - m_matchDelegate->setParent(this); + if (m_matchDelegate) + m_matchDelegate->setParent(this); emit matchDelegateChanged(); } } @@ -157,12 +166,44 @@ void ProcessBackendFactory::setRewriteDelegate(RewriteDelegate *rewriteDelegate) if (m_rewriteDelegate) delete m_rewriteDelegate; m_rewriteDelegate = rewriteDelegate; - m_rewriteDelegate->setParent(this); + if (m_rewriteDelegate) + m_rewriteDelegate->setParent(this); emit rewriteDelegateChanged(); } } /*! + Return true if the factory is requesting idle CPU cycles + */ + +bool ProcessBackendFactory::idleCpuRequest() const +{ + return m_idleCpuRequest; +} + +/*! + Set the current idle CPU request value to \a value + */ + +void ProcessBackendFactory::setIdleCpuRequest(bool value) +{ + if (value != m_idleCpuRequest) { + m_idleCpuRequest = value; + emit idleCpuRequestChanged(); + } +} + +/*! + This virtual function gets called when idle CPU is available. + Subclasses should override this function. + */ + +void ProcessBackendFactory::idleCpuAvailable() +{ + qDebug() << Q_FUNC_INFO; +} + +/*! \fn bool ProcessBackendFactory::canCreate(const ProcessInfo& info) const Return true if this ProcessBackendFactory matches the ProcessInfo \a info @@ -208,6 +249,12 @@ void ProcessBackendFactory::rewrite(ProcessInfo& info) */ /*! + \fn void ProcessBackendFactory::idleCpuRequestChanged() + + Signal emitted whenever the idle CPU request is changed +*/ + +/*! \fn ProcessBackend * ProcessBackendFactory::create(const ProcessInfo& info, QObject *parent) Create a ProcessBackend object based on the ProcessInfo \a info and \a parent. diff --git a/src/core/processbackendfactory.h b/src/core/processbackendfactory.h index 3600ed7..ed17d61 100644 --- a/src/core/processbackendfactory.h +++ b/src/core/processbackendfactory.h @@ -57,6 +57,7 @@ class Q_ADDON_PROCESSMANAGER_EXPORT ProcessBackendFactory : public QObject Q_OBJECT Q_PROPERTY(MatchDelegate* matchDelegate READ matchDelegate WRITE setMatchDelegate NOTIFY matchDelegateChanged); Q_PROPERTY(RewriteDelegate* rewriteDelegate READ rewriteDelegate WRITE setRewriteDelegate NOTIFY rewriteDelegateChanged); + Q_PROPERTY(bool idleCpuRequest READ idleCpuRequest NOTIFY idleCpuRequestChanged) public: ProcessBackendFactory(QObject *parent = 0); @@ -70,20 +71,27 @@ public: MatchDelegate * matchDelegate() const; void setMatchDelegate(MatchDelegate *); + RewriteDelegate * rewriteDelegate() const; void setRewriteDelegate(RewriteDelegate *); + bool idleCpuRequest() const; + virtual void idleCpuAvailable(); + signals: void matchDelegateChanged(); void rewriteDelegateChanged(); + void idleCpuRequestChanged(); protected: virtual void handleMemoryRestrictionChange(); + virtual void setIdleCpuRequest(bool); protected: MatchDelegate *m_matchDelegate; RewriteDelegate *m_rewriteDelegate; bool m_memoryRestricted; + bool m_idleCpuRequest; }; QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/processbackendmanager.cpp b/src/core/processbackendmanager.cpp index 9e00602..5b1b414 100644 --- a/src/core/processbackendmanager.cpp +++ b/src/core/processbackendmanager.cpp @@ -40,6 +40,7 @@ #include "processbackendmanager.h" #include "processbackendfactory.h" #include "processbackend.h" +#include "timeoutidledelegate.h" QT_BEGIN_NAMESPACE_PROCESSMANAGER @@ -69,16 +70,65 @@ QT_BEGIN_NAMESPACE_PROCESSMANAGER The backend manager does not get involved in starting or tracking the lifetime of a process. In general, you should use the ProcessManager class for processes, which contains a backend manager object. + + You may assign an IdleDelegate to the process manager. Certain factory + objects required processing time to launch prelaunched runtime processes. + An IdleDelegate is a class that lets the process manager know when the + system load is low so that the prelaunch programs can be started. If + you do not assign an IdleDelegate, you may subclass the ProcessBackendManager + to override the default idle calculations. + + If you do not assign an IdleDelegate, the TimeoutIdleDelegate will be + used by default. + + If you prefer to not use delegates, you can subclass ProcessBackendManager + and override the \l{handleIdleCpuRequest()} function. If you do this, + you must shut off the default IdleDelegate. For example: + + \code + class MyManager : public ProcessBackendManager { + public + MyManager(QObject *parent=0) : ProcessBackendManager(parent) { + setIdleDelegate(0); + connect(&timer, SIGNAL(timeout()), SLOT(checkCpuLoad())); + timer.setInterval(1000); + } + + protected: + virtual void handleIdleCputRequest(bool request) { + if (request) timer.start(); + else timer.stop(); + } + + protected slots: + void checkCpuLoad() { + if (calcCpuLoad() < 50) + idleCpuAvailable(); // Call the Idle CPU function + } + + private: + QTimer timer; + } + \endcode +*/ + +/*! + \property ProcessBackendManager::idleDelegate + \brief The IdleDelegate object assigned to this factory. */ /*! Construct a ProcessBackendManager with an optional \a parent + By default, a TimeoutIdleDelegate is assigned to the idleDelegate. */ ProcessBackendManager::ProcessBackendManager(QObject *parent) : QObject(parent) , m_memoryRestricted(false) + , m_idleCpuRequest(false) { + m_idleDelegate = new TimeoutIdleDelegate(this); + connect(m_idleDelegate, SIGNAL(idleCpuAvailable()), SLOT(idleCpuAvailable())); } /*! @@ -115,6 +165,8 @@ void ProcessBackendManager::addFactory(ProcessBackendFactory *factory) m_factories.append(factory); factory->setParent(this); factory->setMemoryRestricted(m_memoryRestricted); + connect(factory, SIGNAL(idleCpuRequestChanged()), SLOT(updateIdleCpuRequest())); + updateIdleCpuRequest(); } /*! @@ -123,10 +175,10 @@ void ProcessBackendManager::addFactory(ProcessBackendFactory *factory) QList<Q_PID> ProcessBackendManager::internalProcesses() { - QList<Q_PID> list; + QList<Q_PID> plist; foreach (ProcessBackendFactory *factory, m_factories) - list.append(factory->internalProcesses()); - return list; + plist.append(factory->internalProcesses()); + return plist; } /*! @@ -137,9 +189,10 @@ QList<Q_PID> ProcessBackendManager::internalProcesses() void ProcessBackendManager::setMemoryRestricted(bool memoryRestricted) { if (m_memoryRestricted != memoryRestricted) { - m_memoryRestricted = memoryRestricted; - foreach (ProcessBackendFactory *factory, m_factories) - factory->setMemoryRestricted(memoryRestricted); + m_memoryRestricted = memoryRestricted; + foreach (ProcessBackendFactory *factory, m_factories) { + factory->setMemoryRestricted(memoryRestricted); + } } } @@ -152,6 +205,90 @@ bool ProcessBackendManager::memoryRestricted() const return m_memoryRestricted; } +/*! + Return the current IdleDelegate object + */ + +IdleDelegate *ProcessBackendManager::idleDelegate() const +{ + return m_idleDelegate; +} + +/*! + Set a new process IdleDelegate object \a idleDelegate. + The ProcessBackendManager takes over parentage of the IdleDelegate. + */ + +void ProcessBackendManager::setIdleDelegate(IdleDelegate *idleDelegate) +{ + if (idleDelegate != m_idleDelegate) { + if (m_idleDelegate) + delete m_idleDelegate; + m_idleDelegate = idleDelegate; + if (m_idleDelegate) { + m_idleDelegate->setParent(this); + connect(m_idleDelegate, SIGNAL(idleCpuAvailable()), SLOT(idleCpuAvailable())); + } + emit idleDelegateChanged(); + m_idleCpuRequest = false; // Force this to be recalculated + updateIdleCpuRequest(); + } +} + +/*! + \fn bool ProcessBackendManager::idleCpuRequest() const + Return \c{true} if we need idle CPU cycles. + */ + +/*! + Idle CPU processing is available. This function distributes + the idle CPU to the first factory that has requested it. + */ + +void ProcessBackendManager::idleCpuAvailable() +{ + foreach (ProcessBackendFactory *factory, m_factories) { + if (factory->idleCpuRequest()) { + factory->idleCpuAvailable(); + return; + } + } +} + +/*! + Update the current idle cpu request status by polling + the factories. + */ + +void ProcessBackendManager::updateIdleCpuRequest() +{ + bool request = false; + foreach (ProcessBackendFactory *factory, m_factories) + request |= factory->idleCpuRequest(); + + if (request != m_idleCpuRequest) { + m_idleCpuRequest = request; + if (m_idleDelegate) + m_idleDelegate->requestIdleCpu(m_idleCpuRequest); + handleIdleCpuRequest(m_idleCpuRequest); + } +} + +/*! + Override this function to customize your handling of Idle CPU requests. + The \a request variable will be \c{true} if Idle CPU events are needed. + */ + +void ProcessBackendManager::handleIdleCpuRequest(bool request) +{ + Q_UNUSED(request); +} + +/*! + \fn void ProcessBackendManager::idleDelegateChanged() + Signal emitted whenever the IdleDelegate is changed. +*/ + #include "moc_processbackendmanager.cpp" QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/processbackendmanager.h b/src/core/processbackendmanager.h index 7bae695..c976cb3 100644 --- a/src/core/processbackendmanager.h +++ b/src/core/processbackendmanager.h @@ -52,10 +52,12 @@ class ProcessFrontend; class ProcessInfo; class ProcessBackendFactory; class ProcessBackend; +class IdleDelegate; class Q_ADDON_PROCESSMANAGER_EXPORT ProcessBackendManager : public QObject { Q_OBJECT + Q_PROPERTY(IdleDelegate* idleDelegate READ idleDelegate WRITE setIdleDelegate NOTIFY idleDelegateChanged); public: explicit ProcessBackendManager(QObject *parent = 0); @@ -68,9 +70,27 @@ public: void setMemoryRestricted(bool); bool memoryRestricted() const; + IdleDelegate * idleDelegate() const; + void setIdleDelegate(IdleDelegate *); + bool idleCpuRequest() const { return m_idleCpuRequest; } + +protected: + virtual void handleIdleCpuRequest(bool request); + +signals: + void idleDelegateChanged(); + +protected slots: + void idleCpuAvailable(); + +private slots: + void updateIdleCpuRequest(); + private: QList<ProcessBackendFactory*> m_factories; + IdleDelegate *m_idleDelegate; bool m_memoryRestricted; + bool m_idleCpuRequest; }; QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/timeoutidledelegate.cpp b/src/core/timeoutidledelegate.cpp new file mode 100644 index 0000000..eeb814e --- /dev/null +++ b/src/core/timeoutidledelegate.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "timeoutidledelegate.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +const int kIdleTimerInterval = 1000; + +/*! + \class TimeoutIdleDelegate + \brief The TimeoutIdleDelegate class generates a periodic timeout. + + The TimeoutIdleDelegate class generates a periodic timeout for + creation of idle resources. This is not an intelligent class - it + doesn't matter what your CPU is doing, it will still generate the + periodic timeout. +*/ + +/*! + \property TimeoutIdleDelegate::idleInterval + \brief Time in milliseconds before a new idle CPU request will be fulfilled + */ + + +/*! + Construct a TimeoutIdleDelegate with an optional \a parent. +*/ + +TimeoutIdleDelegate::TimeoutIdleDelegate(QObject *parent) + : IdleDelegate(parent) +{ + connect(&m_timer, SIGNAL(timeout()), SIGNAL(idleCpuAvailable())); + m_timer.setInterval(kIdleTimerInterval); +} + +/*! + \fn void TimeoutIdleDelegate::requestIdleCpu(bool request) + + Turn on or off idle requests based on \a request + You must override this function in a subclass. +*/ + +void TimeoutIdleDelegate::requestIdleCpu(bool request) +{ + if (request != m_timer.isActive()) { + if (request) + m_timer.start(); + else + m_timer.stop(); + } +} + +/*! + Return the current launch interval in milliseconds + */ + +int TimeoutIdleDelegate::idleInterval() const +{ + return m_timer.interval(); +} + +/*! + Set the current idle interval to \a interval milliseconds +*/ + +void TimeoutIdleDelegate::setIdleInterval(int interval) +{ + if (m_timer.interval() != interval) { + bool active = m_timer.isActive(); + m_timer.stop(); + m_timer.setInterval(interval); + if (active) + m_timer.start(); + emit idleIntervalChanged(); + } +} + +/*! + \fn void TimeoutIdleDelegate::idleIntervalChanged() + This signal is emitted when the idleInterval is changed. + */ + + +#include "moc_timeoutidledelegate.cpp" + +QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/timeoutidledelegate.h b/src/core/timeoutidledelegate.h new file mode 100644 index 0000000..98199a8 --- /dev/null +++ b/src/core/timeoutidledelegate.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TIMEOUT_IDLE_DELEGATE_H +#define TIMEOUT_IDLE_DELEGATE_H + +#include <QTimer> +#include "idledelegate.h" + +QT_BEGIN_NAMESPACE_PROCESSMANAGER + +class ProcessInfo; + +class Q_ADDON_PROCESSMANAGER_EXPORT TimeoutIdleDelegate : public IdleDelegate +{ + Q_OBJECT + Q_PROPERTY(int idleInterval READ idleInterval WRITE setIdleInterval NOTIFY idleIntervalChanged) + +public: + explicit TimeoutIdleDelegate(QObject *parent = 0); + virtual void requestIdleCpu(bool request); + + int idleInterval() const; + void setIdleInterval(int interval); + +signals: + void idleIntervalChanged(); + +private: + Q_DISABLE_COPY(TimeoutIdleDelegate); + QTimer m_timer; +}; + +QT_END_NAMESPACE_PROCESSMANAGER + +#endif // TIMEOUT_IDLE_DELEGATE_H diff --git a/tests/auto/processmanager/tst_processmanager.cpp b/tests/auto/processmanager/tst_processmanager.cpp index cd1a3a4..3ea570e 100644 --- a/tests/auto/processmanager/tst_processmanager.cpp +++ b/tests/auto/processmanager/tst_processmanager.cpp @@ -53,6 +53,7 @@ #include "qjsondocument.h" #include "pipeprocessbackendfactory.h" #include "socketprocessbackendfactory.h" +#include "timeoutidledelegate.h" #include <signal.h> @@ -979,13 +980,15 @@ void tst_ProcessManager::prelaunchChildAbort() // The factory should not have launched QVERIFY(manager->internalProcesses().count() == 0); + TimeoutIdleDelegate *delegate = qobject_cast<TimeoutIdleDelegate *>(manager->idleDelegate()); + QVERIFY(delegate); - waitForInternalProcess(manager, 1, factory->launchInterval() + 2000); + waitForInternalProcess(manager, 1, delegate->idleInterval() + 2000); Q_PID pid = manager->internalProcesses().at(0); // Kill the prelaunched process and verify that it is restarted ::kill(pid, SIGKILL); waitForInternalProcess(manager, 0); - waitForInternalProcess(manager, 1, factory->launchInterval() + 2000); + waitForInternalProcess(manager, 1, delegate->idleInterval() + 2000); delete manager; } diff --git a/tests/manual/cpuload/.gitignore b/tests/manual/cpuload/.gitignore new file mode 100644 index 0000000..9613bc1 --- /dev/null +++ b/tests/manual/cpuload/.gitignore @@ -0,0 +1 @@ +tst_cpuload diff --git a/tests/manual/cpuload/cpuload.pro b/tests/manual/cpuload/cpuload.pro new file mode 100644 index 0000000..d6b9897 --- /dev/null +++ b/tests/manual/cpuload/cpuload.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_cpuload +CONFIG -= app_bundle +QT += processmanager +QT -= gui + +SOURCES = tst_cpuload.cpp diff --git a/tests/manual/cpuload/tst_cpuload.cpp b/tests/manual/cpuload/tst_cpuload.cpp new file mode 100644 index 0000000..4037931 --- /dev/null +++ b/tests/manual/cpuload/tst_cpuload.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QCoreApplication> +#include <QStringList> +#include <QDebug> + +#include <cpuidledelegate.h> +#include <iostream> + +QT_USE_NAMESPACE_PROCESSMANAGER + +QString progname; + +class Target : public QObject { + Q_OBJECT + +public slots: + void loadUpdate(double value) { + std::cout << value << std::endl; + } + void idleCpuAvailable() { + std::cout << "idle "; + } +}; + +static void usage() +{ + qWarning("Usage: %s [ARGS]\n", qPrintable(progname)); + exit(1); +} + +int +main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QStringList args = QCoreApplication::arguments(); + progname = args.takeFirst(); + while (args.size()) { + QString arg = args.at(0); + if (!arg.startsWith('-')) + break; + args.removeFirst(); + if (arg == QLatin1String("-help")) + usage(); + } + + if (args.size()) + usage(); + + CpuIdleDelegate cpu; + Target t; + QObject::connect(&cpu, SIGNAL(loadUpdate(double)), &t, SLOT(loadUpdate(double))); + QObject::connect(&cpu, SIGNAL(idleCpuAvailable()), &t, SLOT(idleCpuAvailable())); + + cpu.requestIdleCpu(true); + return app.exec(); +} + +#include "tst_cpuload.moc" |