J'ai commencé à apprendre le multithread et j'ai rencontré des contrats à terme et des promesses de synchronisation des threads sur des ressources partagées. J'ai donc pensé mettre en œuvre un fameux problème de Double Buffering en utilisant Futures and Promises (producteur unique et consommateur unique). La méthodologie de base ce que j'ai pensé est:Mise en œuvre de la double mise en mémoire tampon à l'aide de contrats à terme et de promesses à l'aide de C++ 11
ProducerThread:
loop:
locks_buffer1_mutex
fills_buffer1
unlocks_buffer1_mutex
passes number 1 to Consumer thread using promise.setvalue()
locks_buffer2_mutex
fills_buffer2
unlocks_buffer2_mutex
passes number 2 to Consumer thread using promise.setvalue()
back_to_loop
ConsumerThread:
loop:
wait_for_value_from_promise
switch
case 1:
lock_buffer1_mutex
process(buffer1)
unlock_buffer1_mutex
print_values
break
case 2:
lock_buffer2_mutex
process(buffer2)
unlock_buffer2_mutex
print_values
break
back_to_loop
Voici le code:
#include <iostream>
#include <thread>
#include <vector>
#include <future>
#include <mutex>
#include <iterator>
std::mutex print_mutex;
std::mutex buffer1_mutex;
std::mutex buffer2_mutex;
std::vector<int> buffer1;
std::vector<int> buffer2;
bool notify;
void DataAcquisition(std::promise<int> &p)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
while(true)
{
{
std::lock_guard<std::mutex> buff1_lock(buffer1_mutex);
for(int i=0;i<200;i++)
{
buffer1.push_back(i);
}
}
p.set_value(1);
{
std::lock_guard<std::mutex> buff2_lock(buffer2_mutex);
for(int i=0;i<200;i++)
{
buffer2.push_back(199-i);
}
}
p.set_value(2);
}
}
void DataExtraction(std::future<int> &f)
{
std::vector<int>::const_iterator first,last;
std::vector<int> new_vector;
std::ostream_iterator<int> outit(std::cout, " ");
while(true)
{
int i = f.get();
std::cout << "The value of i is :" << i << std::endl;
switch(i)
{
case 1:
{
std::lock_guard<std::mutex> buff1_lock(buffer1_mutex);
first = buffer1.begin();
last = first + 10;
}
new_vector = std::vector<int>(first,last);
{
std::lock_guard<std::mutex> print_lock(print_mutex);
std::copy(new_vector.begin(),new_vector.end(),outit);
}
break;
case 2:
{
std::lock_guard<std::mutex> buff2_lock(buffer2_mutex);
first = buffer2.begin();
last = first + 10;
}
new_vector = std::vector<int>(first,last);
{
std::lock_guard<std::mutex> print_lock(print_mutex);
std::copy(new_vector.begin(),new_vector.end(),outit);
}
break;
}
}
}
int main()
{
std::promise<int> p;
std::future<int> f = p.get_future();
std::thread thread1(DataAcquisition,std::ref(p));
std::thread thread2(DataExtraction,std::ref(f));
thread1.join();
thread2.join();
return 0;
}
Quand j'exécuter ce code, je suis tombé par son problème giagntic, que je suis ignorant totalement
terminate called after throwing an instance of 'std::future_error' terminate called recursively
what(): 0 1 2 3 4 5 6 7 8 9 Promise already satisfied
Press <RETURN> to close the window
Je googled sur cette erreur, il est suggéré de relier commutateur -lpthread pendant la liaison et la compilation. mais n'a pas pu résoudre le problème.
S'il vous plaît aidez-moi, où vais-je mal ..
Pour ce que vous essayez de faire, un atome ne suffirait-il pas pour indiquer le dernier tampon terminé? Notez qu'il n'y a aucune garantie que le «consommateur» verra toutes les images produites par le «producteur». C'est facile à voir intuitivement si vous imaginez que les «valeurs d'impression» sont lentes. Le consommateur ne détient aucun verrou pendant les 'valeurs d'impression' et le 'Producteur' pourrait faire des cliquetis en produisant un nombre quelconque de cadres et en les écrivant. Même si cela ne vous dérange pas de 'laisser tomber les cadres' une coopération plus subtile signifierait que vous ne gaspillez pas les cycles de CPU produisant des résultats que personne ne voit jamais. – Persixty
Par un argument similaire 'Consumer' pourrait traiter le même cadre deux fois. – Persixty