Guest User

parallelworkers.cpp

a guest
Aug 14th, 2015
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.63 KB | None | 0 0
  1. #include "parallelworkers.h"
  2.  
  3. // Qt includes
  4.  
  5. #include <QCoreApplication>
  6. #include <QEvent>
  7. #include <QMetaMethod>
  8. #include <QMutex>
  9. #include <QThread>
  10. #include <QMetaType>
  11. #include <QWaitCondition>
  12.  
  13. // Local includes
  14.  
  15. #include "digikam_debug.h"
  16. #include "threadmanager.h"
  17.  
  18. namespace Digikam
  19. {
  20.  
  21. ParallelWorkers::ParallelWorkers()
  22.     : m_currentIndex(0),
  23.       m_replacementMetaObject(0)
  24. {
  25. }
  26.  
  27. ParallelWorkers::~ParallelWorkers()
  28. {
  29.     foreach(WorkerObject* const object, m_workers)
  30.     {
  31.         delete object;
  32.     }
  33.     delete m_replacementMetaObject;
  34. }
  35.  
  36. int ParallelWorkers::optimalWorkerCount()
  37. {
  38.     return qMax(1, QThread::idealThreadCount());
  39. }
  40.  
  41. bool ParallelWorkers::optimalWorkerCountReached() const
  42. {
  43.     return m_workers.size() >= optimalWorkerCount();
  44. }
  45.  
  46. void ParallelWorkers::schedule()
  47. {
  48.     foreach(WorkerObject* const object, m_workers)
  49.     {
  50.         object->schedule();
  51.     }
  52. }
  53.  
  54. void ParallelWorkers::deactivate(WorkerObject::DeactivatingMode mode)
  55. {
  56.     foreach(WorkerObject* const object, m_workers)
  57.     {
  58.         object->deactivate(mode);
  59.     }
  60. }
  61.  
  62. void ParallelWorkers::wait()
  63. {
  64.     foreach(WorkerObject* const object, m_workers)
  65.     {
  66.         object->wait();
  67.     }
  68. }
  69.  
  70. void ParallelWorkers::setPriority(QThread::Priority priority)
  71. {
  72.     foreach(WorkerObject* const object, m_workers)
  73.     {
  74.         object->setPriority(priority);
  75.     }
  76. }
  77.  
  78. void ParallelWorkers::add(WorkerObject* const worker)
  79. {
  80.     /*
  81.     if (!asQObject()->inherits(worker->metaObject()->className()))
  82.     {
  83.         qCDebug(DIGIKAM_GENERAL_LOG) << "You need to derive the ParallelWorkers class from the WorkerObject you want to use";
  84.         return;
  85.     }
  86.  
  87.     QMetaObject* meta = asQObject()->metaObject();
  88.     for (int i=0; i<meta->methodCount(); i++)
  89.     {
  90.         QMetaMethod method = meta->method(index);
  91.         if (!method->methodType() == QMetaMethod::
  92.     }
  93.     */
  94.  
  95.     m_workers << worker;
  96. }
  97.  
  98.  
  99. bool ParallelWorkers::connect(const char* const signal,
  100.                               const QObject* const receiver, const char* const method,
  101.                               Qt::ConnectionType type) const
  102. {
  103.     foreach(WorkerObject* const object, m_workers)
  104.     {
  105.         if (!QObject::connect(object, signal, receiver, method, type))
  106.         {
  107.             return false;
  108.         }
  109.     }
  110.     return true;
  111.  
  112. }
  113.  
  114. int ParallelWorkers::replacementStaticQtMetacall(QMetaObject::Call _c, int _id, void **_a)
  115. {
  116.     if (_c == QMetaObject::InvokeMetaMethod)
  117.     {
  118.         // This is the common ancestor's meta object, below WorkerObject
  119.         const QMetaObject* const mobj = mocMetaObject();
  120.         const int properMethods       = mobj->methodCount() - mobj->methodOffset();
  121.  
  122.         if (_id >= properMethods)
  123.         {
  124.             return _id - properMethods;
  125.         }
  126.  
  127.         // Get the relevant meta method. I'm not quite sure if this is rock solid.
  128.         QMetaMethod method = mobj->method(_id + mobj->methodOffset());
  129.  
  130.         // Copy the argument data - _a is going to be deleted in our current thread
  131.         QList<QByteArray> types = method.parameterTypes();
  132.         QVector<QGenericArgument> args(10);
  133.  
  134.         for (int i = 0; i < types.size(); i++)
  135.         {
  136.             qCWarning(DIGIKAM_GENERAL_LOG) << "Datatype" << types[i] << ".";
  137.             int typeId = QMetaType::type(types[i].constData());
  138.  
  139.             if (!typeId && _a[i+1])
  140.             {
  141.                 qCWarning(DIGIKAM_GENERAL_LOG) << "Unable to handle unregistered datatype" << types[i] << "Dropping signal.";
  142.                 return _id - properMethods;
  143.             }
  144.  
  145.             // we use QMetaType to copy the data. _a[0] is reserved for a return parameter.
  146.             void* const data = QMetaType(typeId).construct(_a[i+1]);
  147.             args[i]          = QGenericArgument(types[i].constData(), data);
  148.                         qDebug() << "Data:" << QLatin1String(types[i].constData());
  149.  
  150.         }
  151.  
  152.         // Find the object to be invoked
  153.         WorkerObject* const obj = m_workers.at(m_currentIndex);
  154.  
  155.         if (++m_currentIndex == m_workers.size())
  156.         {
  157.             m_currentIndex = 0;
  158.         }
  159.         obj->schedule();
  160.  
  161.         // Invoke across-thread
  162.         method.invoke(obj, Qt::QueuedConnection,
  163.                       args[0],
  164.                       args[1],
  165.                       args[2],
  166.                       args[3],
  167.                       args[4],
  168.                       args[5],
  169.                       args[6],
  170.                       args[7],
  171.                       args[8],
  172.                       args[9]);
  173.  
  174.         return _id - properMethods; // this return is used by replacementQtMetacall
  175.     }
  176.     else
  177.     {
  178.         m_originalStaticMetacall(asQObject(), _c, _id, _a);
  179.     }
  180.     return _id; // this return will be ignored (qt_static_metacall is void)
  181. }
  182.  
  183. int ParallelWorkers::replacementQtMetacall(QMetaObject::Call _c, int _id, void **_a)
  184. {
  185.     _id = WorkerObjectQtMetacall(_c, _id, _a);
  186.     if (_id < 0)
  187.         return _id;
  188.  
  189.     if (_c == QMetaObject::InvokeMetaMethod)
  190.     {
  191.         return replacementStaticQtMetacall(_c, _id, _a);
  192.     }
  193.  
  194.     return _id;
  195. }
  196.  
  197. const QMetaObject *ParallelWorkers::replacementMetaObject() const
  198. {
  199.     if (!m_replacementMetaObject)
  200.     {
  201.         QMetaObject *rmo = new QMetaObject(*mocMetaObject());
  202.         ParallelWorkers* nonConstThis = const_cast<ParallelWorkers*>(this);
  203.         nonConstThis->m_originalStaticMetacall = rmo->d.static_metacall;
  204.         rmo->d.static_metacall = nonConstThis->staticMetacallPointer();
  205.         nonConstThis->m_replacementMetaObject  = rmo;
  206.     }
  207.     return m_replacementMetaObject;
  208. }
  209.  
  210. } // namespace Digikam
Advertisement
Add Comment
Please, Sign In to add comment