2010-05-24 4 views
1

Je me prépare pour une interview dans quelques semaines et je pense que je donnerais un fil à retordre, ainsi que le simple problème producteur/consommateur que j'ai appris à l'école. Je l'ai pas fait tout à fait un certain temps, donc j'étais curieux de savoir ce que vous en pensez? Que dois-je ajouter pour en faire un meilleur exemple, etc. Merci pour les commentaires! :)Mise en œuvre du producteur/consommateur - Feedback Wanted

////////////////////////////////////////////////////////////////////////// 
boost::mutex bufferMutex; 
deque<int> buffer; 
const int maxBufferSize = 5; 
////////////////////////////////////////////////////////////////////////// 

bool AddToBuffer(int i) 
{ 
    if (buffer.size() < maxBufferSize) 
    { 
     buffer.push_back(i); 
     return true; 
    } 
    else 
    {  
     return false; 
    } 
} 

bool GetFromBuffer(int& toReturn) 
{ 
    if (buffer.size() == 0) 
    { 
     return false; 
    } 
    else 
    { 
     toReturn = buffer[buffer.size()-1]; 
     buffer.pop_back(); 
     return true; 
    } 
} 

struct Producer 
{ 
    int ID; 
    void operator()() 
    { 
     while (true) 
     { 
      boost::mutex::scoped_lock lock(bufferMutex); 
      int num = dice(); 
      bool result = AddToBuffer(num); 
      lock.unlock(); 
      //safe area done 
      if (result) 
      { 
       cout << "Producer " << this->ID << " Added " << num << endl; 
      } 
      else 
      { 
       cout << "!!Buffer was Full!!" << endl; 
      } 
      //Added 
      //Now wait 
      boost::xtime xt; 
      xtime_get(&xt, boost::TIME_UTC); 
      xt.nsec += 1000000 + 100000 * (rand() % 1000); 
      boost::thread::sleep(xt); 
     } 
    } 
}; 

struct Consumer 
{ 
    int ID; 
    void operator()() 
    { 
     while (true) 
     { 
      int returnedInt = 0; 
      boost::mutex::scoped_lock lock(bufferMutex); 
      bool result = GetFromBuffer(returnedInt); 
      lock.unlock(); 
      //safe area done 
      if (result) 
      { 
       cout << "\tConsumer " << this->ID << " Took Out " << returnedInt << endl; 
      } 
      else 
      { 
       cout << "!!Buffer was Empty!!" << endl; 
      } 
      //Added 
      //Now wait 
      boost::xtime xt; 
      xtime_get(&xt, boost::TIME_UTC); 
      xt.nsec += 1000000 + 100000 * (rand() % 1000); 
      boost::thread::sleep(xt); 
     } 
    } 
}; 



void main() 
{ 
    Producer p, p2; 
    Consumer c, c2; 

    p.ID = 1; 
    p2.ID = 2; 

    c.ID = 1; 
    c2.ID = 2; 

    boost::thread thread1(boost::ref(p)); 
    boost::thread thread2(boost::ref(c)); 
    boost::thread thread3(boost::ref(p2)); 
    boost::thread thread4(boost::ref(c2)); 

    int x; 
    cin >> x; 
} 

Répondre

3

Si vous êtes déjà l'emballage de votre objet tampon dans les appels comme AddToBuffer et GetFromBuffer, il serait plus logique pour vous de mettre le verrouillage au sein de vos fonctions wrapper. En outre, vous faites un appel explicite à déverrouiller, ce qui annule complètement le but de scoped_lock; scoped_lock utilise l'acquisition de ressources initialisée (RAII) pour acquérir et libérer le verrou. Une meilleure utilisation consisterait à placer la section critique dans un bloc afin que le mutex soit libéré car le verrou sort de la portée plutôt que d'un appel explicite à la fonction de déverrouillage, car les étendues sont moins fragiles. Par exemple:

// Code that doesn't need locking 
{ 
    boost::mutex::scoped_lock lck(bufferMutex); // Lock is acquired here 
    // Code that needs to be synchronized 
} // Lock is automatically released here without explicit call to unlock() 
// More code that doesn't need locking 
+1

Merci pour le commentaire! :) – bobber205