Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- Copyright (c) 2013 Oliveri Dario
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include <mutex>
- #include <iostream>
- /** Semplice sistema di loggin per fare debug e vedere cosa viene stampato.
- * Un mutex globale è utilizzato per scrivere messaggi su console (ricordo
- * che la console è una risorsa e ogni risorsa va protetta da un mutex in
- * presenza di processi paralleli che la usano).*/
- #if 0 //E' possibile cambiare 0 con 1 per disattivare i messaggi di debug.
- #define DEBUG_LOG(X) (void(0))
- #else
- std::mutex GlobalMutex;
- #define DEBUG_LOG(x) \
- GlobalMutex.lock(); \
- std::cout<<x<<std::endl; \
- GlobalMutex.unlock();
- #endif
- typedef int ProducerMessage;
- /*******************************************************************************
- * SharedBuffer, risorsa condivisa tra 2 thread per potersi scambiare messaggi.
- * Non è vietato utilizzarla per più di 2 thread, ma solitamente è più
- * conveniente utilizzare un buffer per ogni canale di comunicazione piuttosto
- * che utilizzare 1 buffer per tutte le comunicazioni.
- *******************************************************************************/
- struct SharedBuffer{
- std::mutex casello;
- ProducerMessage messages[8];
- // possiamo inizializzare qui e risparmiarci il costruttore.
- int separator = 0;
- int reader = 0;
- int writer = 0;
- //ritorna true se il messaggio è stato scritto in out_m
- bool readMessage(ProducerMessage & out_m){
- casello.lock(); //entro nel "casello autostradale"
- if(separator == 0){
- //DEBUG_LOG("No message to read!");
- casello.unlock(); //esco dal "casello"
- return false;
- }
- out_m = messages[reader]; //copio messaggio su out_m
- reader++; //aggiorno posizione del reader
- if(reader > 7)
- reader=0;
- separator --;
- casello.unlock(); //esco dal "casello"
- return true;
- }
- //ritorna true se il messaggio è stato scritto dentro il buffer
- bool writeMessage(ProducerMessage in){
- casello.lock(); //entro nel casello
- if(separator==7){
- //DEBUG_LOG("no empty space left");
- casello.unlock();
- return false;
- }
- messages[writer]=in; //scrivo il messaggio dentro al buffer
- writer++;
- if(writer > 7)
- writer=0;
- separator++;
- casello.unlock();
- return true; //esco dal casello
- }
- };
- #include <cstdlib> //serve per "rand()".
- class Producer{
- SharedBuffer * buffer;
- public:
- /** Costruttore */
- Producer(SharedBuffer * abuffer):
- buffer(abuffer){ }
- void run(){
- for(int i=0; i<16; i++){
- int r = std::rand()%2; //numero casuale ritorna 0 oppure 1.
- ProducerMessage mess = r;
- switch(r){
- case 0:
- DEBUG_LOG("producer -> 0"); break;
- case 1:
- DEBUG_LOG("producer -> 1"); break;
- }
- //Attesa attiva che si liberi il buffer dei messaggi. In un
- //codice reale si può imporre un limite alla durata dell'attesa
- while(!buffer->writeMessage(mess)){}
- }
- // Questo messaggio chiude il consumer.
- DEBUG_LOG("producer -> 5");
- while(!buffer->writeMessage(5)){}
- }
- };
- class Consumer{
- SharedBuffer * buffer;
- public:
- /** Costruttore*/
- Consumer(SharedBuffer * abuffer):
- buffer(abuffer){ }
- void run(){
- ProducerMessage mess;
- while(mess!=5){
- if(buffer->readMessage(mess)){
- switch(mess){
- case 0:
- DEBUG_LOG("consumed 0!"); break;
- case 1:
- DEBUG_LOG("consumed 1!"); break;
- }
- }
- }
- DEBUG_LOG("consumed Quit");
- }
- };
- #include <thread>
- int main(){
- SharedBuffer buffer;
- Producer B(&buffer);
- Consumer C(&buffer);
- std::thread consumerThread(&Consumer::run,&C);
- std::thread producerThread(&Producer::run,&B);
- consumerThread.join();
- producerThread.join();
- DEBUG_LOG("THE END");
- return 0;
- }
- /** OUTPUT EXAMPLE
- producer -> 1
- producer -> 1
- producer -> 0
- producer -> 0
- producer -> 1
- producer -> 0
- producer -> 0
- producer -> 0
- consumed 1!
- producer -> 0
- consumed 1!
- producer -> 0
- consumed 0!
- producer -> 1
- consumed 0!
- producer -> 1
- consumed 1!
- producer -> 1
- consumed 0!
- consumed 0!
- consumed 0!
- consumed 0!
- consumed 0!
- consumed 1!
- consumed 1!
- consumed 1!
- producer -> 1
- consumed 1!
- producer -> 1
- producer -> 1
- consumed 1!
- producer -> 5
- consumed 1!
- consumed Quit
- THE END
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement