[C++] Problema con le thread

Messaggioda ilsaggio » 14/04/2022, 12:50

Ciao a tutti :) ho da poco iniziato a fare esercizi sulle thread ed ovviamente ho i primi problemi :(
Devo svolgere questo semplice esercizio dove ho un buffer, in cui devo inserire dei dati presi da un file input_file.txt, ad esempio questo:
1
2
3
4
Questi dati poi vengono letti e inseriti nel buffer con la funzione lettura_posizione e poi vengono letti e scritti a terminale con la funzione scrittura_posizione, il tutto gestendo l'accesso al buffer.
Questo è il buffer:
Codice:
// Buffer.h

#ifndef Buffer_h
#define Buffer_h

#include <queue>
using std::queue;
#include <mutex>
using std::mutex;
#include <condition_variable>
using std::condition_variable;

class Buffer
{
    public:
        void append(double v);
        double take();

    private:
        queue<double> buffer_;
        mutex mutex_;
        condition_variable not_empty_;       
};

void lettura_posizione(Buffer buf);
void model(Buffer buf);

#endif

Codice:
//Buffer.cpp
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <string>
using std::string;
#include <mutex>
using std::mutex;
using std::unique_lock;
#include <condition_variable>
using std::condition_variable;

#include "Buffer.h"

void Buffer::append(double shift)
{
    unique_lock<mutex> mlock(mutex_);
    buffer_.push(shift);
    not_empty_.notify_one(); //signalC
}

double Buffer::take()
{
    unique_lock<mutex> mlock(mutex_);
    while(buffer_.empty())
        not_empty_.wait(mlock); //waitC
    double posit =buffer_.front();
    buffer_.pop();
    return posit;
}

void lettura_posizione(Buffer buf)
{
    //Prendo i dati di input da un file txt
    ifstream input("input_file.txt");
        if(!input.is_open())
    {
        cout << "Unable to open the input file." << endl;
        exit(EXIT_FAILURE);
    }
   string line;
   while (getline (input, line)){
        size_t pos = line.find_first_of(" ",0);
        double position = stod(line.substr(pos+1,line.size()));
        buf.append(position);
    }
}

void scrittura_posizione(Buffer buf)
{
    for(int i=0; i<4; i++){
            double pos= buf.take();
            cout<<pos<<endl;
    }
}


E il main è questo:
Codice:
#include <iostream>
using std::cout;
using std::endl;
#include <thread>
using std::thread;


#include "Buffer.h"

Buffer b1;

int main(int argc, char* argv[])
{
    thread lettura{lettura_posizione, b1};
    thread scrittura{scrittura_posizione, b1};

    lettura.join();
    scrittura.join();
   
    cout << "End of main thread." << endl;

    return 0;
}

Il problema è che quando compilo mi esce questo errore:
Codice:
In file included from main.cpp:4:
/usr/include/c++/9/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(Buffer); _Args = {Buffer&}; <template-parameter-1-3> = void]’:
main.cpp:47:41:   required from here
/usr/include/c++/9/thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
  120 |           typename decay<_Args>::type...>::value,
      |                                            ^~~~~
/usr/include/c++/9/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(Buffer), Buffer> >’:
/usr/include/c++/9/thread:131:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(Buffer); _Args = {Buffer&}; <template-parameter-1-3> = void]’
main.cpp:47:41:   required from here
/usr/include/c++/9/thread:243:4: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(Buffer), Buffer> >::__result<std::tuple<void (*)(Buffer), Buffer> >’
  243 |    _M_invoke(_Index_tuple<_Ind...>)
      |    ^~~~~~~~~
/usr/include/c++/9/thread:247:2: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(Buffer), Buffer> >::__result<std::tuple<void (*)(Buffer), Buffer> >’
  247 |  operator()()
      |  ^~~~~~~~


Qualcuno sa dove sbaglio e può aiutarmi? Grazie :D
Ultima modifica di ilsaggio il 15/04/2022, 09:17, modificato 1 volta in totale.
Avatar utente
ilsaggio
Junior Member
Junior Member
 
Messaggio: 220 di 440
Iscritto il: 12/12/2016, 22:08

Re: [C++] Problema con le thread

Messaggioda Quinzio » 15/04/2022, 02:04

Allora, il problema e' tedioso da capire e da comprendere.
Anche per me comunque sono argomenti in parte oscuri.

Comunque, provo a spiegartelo.
La classe thread sostanzialmente lancia la funzione che tu gli hai impostato, con i suoi argomenti.
Ora, gli argomenti sono passati facendo il forward di un reference.
Questa espressione oscura significa che devi passargli un puntatore alla classe Buffer e non l'oggetto stesso, il Buffer b1 ad esempio.
Questo perche' l'oggetto potrebbe ancora non esistere al momento della creazione del thread, ma esistere quando viene lanciato.
La conclusione e' che bisogna usare un reference, come ti faccio vedere nel codice che copio.
Vedi che ad es. una delle funzioni del thread cambia cosi':
void scrittura_posizione(Buffer &buf)

In ogni caso, a parte l'errore che da il compilatore, il fatto che tu non abbia usato dei puntatori ma hai passato alla funzione l'oggetto stesso, e' un errore grave e mostra che non hai compreso bene come avviene il passaggio degli argomenti (per value o per reference) e cosa comporta cio' nel caso che l'argomento sia un oggetto.

Ti lascio alcuni link che sicuramente spiegano il tutto molto meglio di come farei io.
https://stackoverflow.com/questions/619 ... e-after-co
https://stackoverflow.com/questions/147 ... -parameter
e poi ti basta cercare su Google.

Codice:
// Buffer.h

#ifndef Buffer_h
#define Buffer_h

#include <queue>
using std::queue;
#include <mutex>
using std::mutex;
#include <condition_variable>
using std::condition_variable;

class Buffer
{
    public:
        void append(double v);
        double take();

    private:
        queue<double> buffer_;
        mutex mutex_;
        condition_variable not_empty_;
};

void lettura_posizione(Buffer &buf);
void scrittura_posizione(Buffer &buf);
void model(Buffer buf);

#endif

//Buffer.cpp
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <string>
using std::string;
#include <mutex>
using std::mutex;
using std::unique_lock;
#include <condition_variable>
using std::condition_variable;

#include "Buffer.h"

void Buffer::append(double shift)
{
    unique_lock<mutex> mlock(mutex_);
    buffer_.push(shift);
    not_empty_.notify_one(); //signalC
}

double Buffer::take()
{
    unique_lock<mutex> mlock(mutex_);
    while(buffer_.empty())
        not_empty_.wait(mlock); //waitC
    double posit =buffer_.front();
    buffer_.pop();
    return posit;
}

void lettura_posizione(Buffer &buf)
{
    //Prendo i dati di input da un file txt
    ifstream input("input_file.txt");
        if(!input.is_open())
    {
        cout << "Unable to open the input file." << endl;
        exit(EXIT_FAILURE);
    }
   string line;
   while (getline (input, line)){
        size_t pos = line.find_first_of(" ",0);
        double position = stod(line.substr(pos+1,line.size()));
        buf.append(position);
    }
}

void scrittura_posizione(Buffer &buf)
{
    for(int i=0; i<4; i++){
            double pos= buf.take();
            cout<<pos<<endl;
    }
}


// main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include <thread>
using std::thread;


#include "Buffer.h"

Buffer b1;

int main(int argc, char* argv[])
{
    thread lettura(lettura_posizione, std::ref(b1));
    thread scrittura(scrittura_posizione, std::ref(b1));

    lettura.join();
    scrittura.join();

    cout << "End of main thread." << endl;

    return 0;
}


Quinzio
Cannot live without
Cannot live without
 
Messaggio: 4855 di 10548
Iscritto il: 24/08/2010, 06:50

Re: [C++] Problema con le thread

Messaggioda ilsaggio » 15/04/2022, 08:22

Grazie!
Avatar utente
ilsaggio
Junior Member
Junior Member
 
Messaggio: 221 di 440
Iscritto il: 12/12/2016, 22:08


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite