static void *startHelper(void *arg) { PipelineStage *stage = (PipelineStage *) arg; qDebug() << "starting " << stage; stage->execute(); return NULL; }
// TODO static DWORD WINAPI startHelper(LPVOID arg) { PipelineStage *stage = (PipelineStage *) arg; qDebug() << "starting " << stage; stage->execute(); return 0; }
void PipelineProcessor::wait() { if (NULL != m_head->m_out_queue) { assert(!this->m_run); // user must call stop() before wait } for (PipelineStage* s = m_head->m_next; s != m_head; s = s->m_next) s->wait(); }
void PipelineProcessor::start() { assert(m_head); assert(total_steps() >= 2 || (total_steps() >= 1 && NULL != m_head->m_out_queue)); m_run = true; if (NULL == m_mutex) { m_mutex = new mutex; m_is_mutex_owner = true; } int plgen = -1, plkeep = -1, nth = 0; (void)plgen; // depress warning for (PipelineStage* s = m_head->m_next; s != m_head; s = s->m_next) { if (PipelineStage::ple_generate == s->m_pl_enum) { assert(-1 == plgen); // only one generator assert(-1 == plkeep); // keep must after generator plgen = nth; } else if (PipelineStage::ple_keep == s->m_pl_enum) { // must have generator before // m_head->m_out_queue is not NULL when data source is external assert(-1 != plgen || m_head->m_out_queue); plkeep = nth; } ++nth; } if (-1 != plkeep) this->m_keepSerial = true; for (PipelineStage* s = m_head->m_next; s != m_head; s = s->m_next) s->start(m_queue_size); }
void PipelineManager::launchParallel(int queueSize) { QDateTime now = QDateTime::currentDateTime(); QString traceDir = QString("trace-%1").arg(now.toString()); traceDir.replace(":", "_"); // Windows n'aime pas les ":" dans les noms de fichiers QDir dir(traceDir); dir.mkpath("."); // Définir le rank (position de l'étape dans le pipeline) for (int i = 0; i < stageList.size(); i++) { PipelineStage *stage = stageList.at(i); stage->setRank(i); SimpleTracer *t = new SimpleTracer(stage); QString stageName = QString("%1-0-%2.data") .arg(i) .arg(stage->name()); QString path = traceDir + QDir::separator() + stageName; t->setPath(path); t->init(); } // Connecter les étapes par des objets ImageQueue for (int i = 0; i < stageList.size() - 1; i++) { PipelineStage *prod = stageList.at(i); PipelineStage *cons = stageList.at(i + 1); ImageQueue *q = new ImageQueue(this, queueSize); qDebug() << "queue " << i << " " << prod << " ---> " << cons; // enregistrer les modifications effectuées à cette queue SimpleTracer *t = new SimpleTracer(q); QString stageName = QString("%1-1-%2-%3.data") .arg(i) .arg(prod->name()) .arg(cons->name()); QString path = traceDir + QDir::separator() + stageName; t->setPath(path); t->init(); stageList.at(i)->setProdQueue(q); stageList.at(i + 1)->setConsQueue(q); } #if defined(Q_OS_LINUX) // Démarrer les fils d'exécutions pthread_t *threads = new pthread_t[stageList.size()]; for (int i = 0; i < stageList.size(); i++) { pthread_create(&threads[i], NULL, startHelper, stageList.at(i)); } // Attendre la fin de l'exécution for (int i = 0; i < stageList.size(); i++) { pthread_join(threads[i], NULL); } delete[] threads; #elif defined(Q_OS_WIN) /* * Démarrer les threads Windows * Attention: utilisez seulement l'API Windows (pas l'API de Qt!) */ HANDLE *threads = new HANDLE[stageList.size()]; DWORD threadIds[stageList.size()]; for (int i = 0; i < stageList.size(); i++) { threads[i] = CreateThread( NULL, NULL, startHelper, (LPVOID)stageList.at(i), 0, &threadIds[i]); } // Attendre la fin de l'exécution WaitForMultipleObjects(stageList.size(), threads, true, INFINITE); for (int i = 0; i < stageList.size(); i++) { CloseHandle(threads[i]); } delete[] threads; #endif }