1
votes

Quelle est la meilleure façon de produire du fil?

Langage du programme: C ++ 11
J'utilise le mode threads de pipeline pour traiter les données.
Un thread génère des données.
Un thread traite les données.
Bien qu'il n'y ait pas de données à traiter, quelle est la meilleure façon de générer un fil de discussion?
Maintenant, j'utilise

std::this_thread::sleep_for(100ms); 
  1. Je me demande s'il existe une meilleure façon de céder?
  2. Si vous dormez suffisamment, combien de temps est-il préférable de dormir?


3 commentaires

Ce n'est pas ce que céder. Ce dont vous avez besoin est une condition d'attente sur laquelle votre thread doit attendre. Voir stackoverflow.com / questions / 10974829 /…


pourquoi la balise pi?


Vous devez utiliser la synchronisation des threads (mutex, condition_variable), laissez le céder au système d'exploitation, s'il vous plaît.


3 Réponses :


2
votes

Introduisez une condition d'attente sur laquelle votre thread consommateur doit attendre. Une fois que les données sont générées par le producteur, il peut notifier votre fil de discussion, jusqu'à ce que le consommateur attende.


0 commentaires

6
votes

Quelle est la meilleure façon de générer du fil de discussion?

C'est std::this_thread::yield.

J'utilise maintenant

std::this_thread::sleep_for(100ms);

Pendant que dormir donne le fil comme effet secondaire, ce n'est pas tout ce qu'il fait. Comme son nom l'indique, il bloque le thread pendant un temps donné.

Cependant, on ne sait pas comment céder ou dormir serait utile dans un cas producteur / consommateur tel que ce que vous décrivez. Ce que vous devriez probablement faire est d'attendre une variable de condition à la place.


0 commentaires

1
votes

Communiquez via une file d'attente de données. La file d'attente peut avoir une taille maximale si vous le souhaitez.

Un thread génère des données et les place dans la file d'attente.

Un autre thread extrait les données de la file d'attente et les traite.

Lorsque la file d'attente est vide, le thread consommateur attend dans la file d'attente de nouvelles données à pousser.

Lorsque la file d'attente est pleine, le thread producteur attend dans la file d'attente que les données soient extraites. Vous pouvez également supprimer et remplacer les données en attente dans la file d'attente. Cela dépend de la nature de votre modèle de données (le plus récent est important ou tout dans l'ordre est important)

File d'attente simple:

template<class T>
struct mono_threadsafe_queue {
  // waits until we have data, then returns it.
  T pop() {
    auto l = lock();
    cv_hasdata.wait( l, [&]{ return (bool)data; } );
    T r = std::move(*data);
    data = boost::none;
    cv_hasroom.notify_one();
    return r;
  }
  // waits for there to be room if there is none.
  void push( T&& t ) {
    auto l = lock();
    cv_hasroom.wait( l, [&]{ return !(bool)data; } );
    data =  std::move(t);
    cv_hasdata.notify_one();
  }
  void replace( T&& t ) {
    auto l = lock();
    data =  std::move(t);
    cv_hasdata.notify_one();
  }
  // replaces data if f returns true, or if there is no data
  // imagine data with a timestamp, and we only want to replace it with
  // newer data
  template<class F>
  void replace_if( T&& t, F&& f ) {
    auto l = lock();
    if (!data || !f(*data))
    {
      data =  std::move(t);
      cv_hasdata.notify_one();
    }
  }
  void abandon() {
    auto l = lock();
    data = boost::none;
    cv_hasroom.notify_one();
  }

private:
  std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(m); }

  std::mutex m;
  std::condition_variable cv_hasdata;
  std::condition_variable cv_hasroom;
  boost::optional<T> data;
};

une avec un la limite sur le nombre d'entrées devrait avoir une deuxième variable condition_variable pour notifier quand quelqu'un apparaît, et push devrait voir si vous êtes à la limite.

Le support "écraser quand plein" devient une autre option. Un élément "le plus récent" ressemble à:

template<class T>
struct threadsafe_queue {
  T pop() {
    auto l = lock();
    cv.wait( l, [&]{ return !data.empty(); } );
    T r = std::move(data.front());
    data.pop_front();
    return r;
  }
  void push( T&& t ) {
    auto l = lock();
    data.push_back( std::move(t) );
    cv.notify_one();
  }
  void abandon() {
    auto l = lock();
    data = {};
  }
private:
  std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(m); }

  std::mutex m;
  std::condition_variable cv;
  std::deque<T> data;
};


0 commentaires