2017-05-06 3 views
0

Ich versuche eine einfache task Klasse zu schreiben. Es ist ein Wrapper um std::future, es seinen Zustand hält (not_started, running, completed), kann die Verarbeitung von bestimmtem Job bei Bedarf starten und es kann immer wieder zurückkehrt aufgrund seiner Verarbeitung.Warten bis eine Aufgabe abgeschlossen ist

Ich kann auch einige globalen Funktionen für die Arbeit mit diesen Aufgaben bieten. Aber ich bin beim Schreiben ein wenig stecken size_t wait_any(std::vector<task<T>>& tasks) Funktion. Diese Funktion erhält einen Vektor von Aufgaben und sollte den Index der ersten abgeschlossenen Aufgabe zurückgeben. Wenn zu Beginn mehr Aufgaben erledigt sind, muss einer von ihnen zurückgegeben werden (aber das ist nicht das Problem).

Eine einfache Implementierung aktive Warte mit folgt:

template <typename T> 
size_t wait_any(std::vector<task<T>>& tasks) { 

    if (tasks.size() == 0) throw std::exception("Waiting for empty vector of tasks!"); 

    for (auto i = tasks.begin(); i != tasks.end(); ++i) { 
     (*i).try_start(); 
    } 

    while (true) { 
     for (size_t i = 0; i != tasks.size(); ++i) { 
      if (tasks[i].is_completed()) return i; 
     } 
    } 
} 

ich passiv warte auf jede fertigstellung schätzen würde. Eine std::this_thread::yield Funktion ist verfügbar, aber ich würde es lieber nicht verwenden. Wie in der Dokumentation erwähnt:

Das genaue Verhalten dieser Funktion hängt von der Implementierung ab, insbesondere von der Mechanik des verwendeten OS-Schedulers und dem Zustand des Systems.

Es scheint, dass ich std::condition_variable und std::mutex verwenden sollte, um die ganze Sache zum Laufen zu bringen. Es gibt eine Menge Beispiele, die den Gebrauch dieser Dinge zeigen, aber ich verstehe es überhaupt nicht und ich habe keine Lösung für dieses spezielle Problem gefunden.

Ich würde vermuten, dass ich eine std::condition_variable (nur cv weiter) in der wait_any Funktion erstellen sollte. Dann sollte dieser cv (Zeiger) für alle Aufgaben von gegebenem Vektor registriert werden. Sobald eine der Aufgaben abgeschlossen ist (ich kann den Moment behandeln, wenn eine Aufgabe erledigt ist), sollte sie std::condition_variable::notify_one für alle in dieser Aufgabe registrierten cv aufrufen. Diese notified cv 's sollten auch von allen Aufgaben entfernt werden, die sie halten.

Nun, ich weiß nicht, wie mutex es zu verwenden. Ich muss wahrscheinlich mehrere Anrufe von Benachrichtigungen und viele andere Probleme verhindern.

Jede Hilfe wird geschätzt!

+0

Dieses Beispiel helfen könnte: http://stackoverflow.com/documentation/c%2b%2b/699/threading/13552/using-condition -variables # t = 201705061205000751576 – didiz

+0

Sie können nicht warten, bis eine Aufgabe abgeschlossen ist, da Sie die gesamte CPU verwenden. – stark

Antwort

0

ich dachte, da Sie nur eine Benachrichtigung benötigen, können Sie verwenden, um die std::call_once task_id einzustellen, die Sie benötigen.

Eine naive Art und Weise, darüber zu gehen wäre:

#include <iostream> 
#include <vector> 
#include <thread> 

    std::once_flag lala; 
    std::atomic_int winner(-1); 

    void silly_task(int task_id) 
    { 
     //do nothing 
     std::call_once (lala, [&]() 
     { 
      std::cout << "thread " << task_id << " wins" << std::endl; 
      winner = task_id; 
     }); 
    } 

    int main(){ 

     std::vector<std::thread> vt; 
     for (int i=0; i < 10 ; i ++) 
     { 
      vt.push_back(std::thread(&silly_task, i)); 

     } 

     while (winner == -1) 
     { 
      std::this_thread::sleep_for(std::chrono::seconds(1)); 
     } 
     for (int i=0; i < 10 ; i ++) 
     { 
      vt[i].join(); 

     } 

     return 0; 
    } // end main 
Verwandte Themen