Create a thread

I need to run two functions at the same time, read temperature and open Menu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
	setlocale(LC_ALL, "Portuguese");
	int n = 2, operacao; //Porta serial inicial e Valor do Menu;
	float qt_leituras, b, intervalo = 2;
	ListaEncadeada<Estado> lista;
	Interface _interface(n);
	c_clrscr();
	_interface.mostraTemperatura(intervalo);
//	thread first{mostraTemperatura, intervalo};//Execução das threads
//	first.join();
	while (true) { //Menu e Programa Principal
//There are any cases here, but not important in the question
	}
	
	return 0;
}


In my .h there are;
1
2
3
4
5
6
7
8
9
	void mostraTemperatura(float intervalo) {
		string _leitura = _s.enviaSerial(0);
		replace(_leitura.begin(), _leitura.end(), '.', ',');
		_temperatura = atof(_leitura.c_str());
		while (true) {
			cout << _temperatura << endl;
			Sleep(intervalo * 1000);
		}
	}

If you just want to run 2 or more function in the same time you don't need to explicitly create threads, instead use std::async

pseudo code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <future>

// 2 functions
void f1(){}
void f2(){}

int main()
{
     // run them in same time
     std::async(f1);
     std::async(f2);

     return 0;
}
Last edited on
But Menu doesn't a function. I need to run the function "mostraTemperatura" and the command while.
I think you mean that mostraTemperatura has arguments?

Just supply the arguments you want, for example:
std::async(mostraTemperatura, 4.32);
Important this part, thanks. But mostraTemperatura are in archive .h.

1
2
3
Interface _interface(n);
	c_clrscr();
	_interface.mostraTemperatura(intervalo);


Other problem is that simultaneously with mostraTemperatura I need to run the command "while". It's possible?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
while (true) { //Menu e Programa Principal
		c_textcolor(BLACK);
		c_textbackground(WHITE);
		cout << "\t\t\tMenu Principal" << endl;
		cout << "\t0\tLer a temperatura e armazenar na lista encadeada" << endl;
		cout << "\t1\tSalvar dados em txt" << endl;
		cout << "\t2\tAjustar intervalo de exibição da temperatura" << endl;
		cout << "\t3\tAjustar limiar de temperatura" << endl;
		cout << "\t4\tLeituras no formato datalog" << endl;
		cout << "\t5\tExportar os dados para o Excel" << endl;
		cout << "\t6\tLimpar todos os dados" << endl;
		cout << "\t7\tLevantamento de ocorrências de uma data" << endl;
		cout << "\t8\tCálculo de valores estatísticos" << endl;
		cout << "\t9\tExportar dados no formato de gráfico" << endl;
		cout << "\t10\tEscolher a porta serial da comunicação" << endl;
		cout << "\t11\tSair" << endl;
		cout << "Digite uma opção do menu: " << endl;

		cin >> operacao;

		switch (operacao) {
		case 0: {
			c_clrscr();
			Estado _estado = _interface.getEstado();
			lista.insereF(_estado);
			break;
		}
		case 1: {
			c_clrscr();
			SalvaDados(lista);
			break;
		}
		case 2: {
			c_clrscr();
			cout
					<< "Entre o intervalo de tempo em que a temperatura é mostrada: "
					<< endl;
			cin >> intervalo;
			break;
		}
		case 3: {
			c_clrscr();
			_interface.setLimites();
			_interface.Controle();
			break;
		}
		case 4: {
			c_clrscr();
			cout << "Digite o número de leituras desejado:";
			cin >> qt_leituras;
			cout << endl << "Escolha o tempo entre cada leitura: ";
			cin >> b;
			//	Datalog g(qt_leituras, b, &s);
			break;
		}
		case 5: {
			c_clrscr();
			EscreveDadosExcel(lista);
			break;
		}
		case 6: {
			c_clrscr();
			LimpaExcel(lista);
			break;
		}
//	case 7:
//		c_clrscr();
			//break;
//	case 8:
//		c_clrscr();
			//break;
//	case 9:
//		c_clrscr();
			//break;
		case 10: {
			c_clrscr();
			cout << "Digite o número da porta serial: " << endl;
			cin >> n;
			_interface.setPorta(n);
			break;
		}
		case 11: {
			c_clrscr();
			SalvaDados(lista);
			exit(0);
			break;
		}
			c_clrscr();
			cout << "\nAperte qualquer tecla, para voltar ao menu" << endl;

		}
	}

	return 0;
}
I write:

 
	async(_interface.mostraTemperatura, intervalo);
the problem I have with your code is that it isn't in english, try to write code always in english primarly because of other people.

now to the problem, the problem I see is that you have to give std::async an object instance because mostraTemperatura is a class non static member function.

normaly you would do this with std::bind
for example:
std::async(std::bind(&_interface::mostraTemperatura, this, intervalo);

this will work only if you call it "inside" the object.
otherwise supply object instance for example:

1
2
_interface object;
std::async(std::bind(&_interface::mostraTemperatura, object, intervalo);


edit:
headers you need:
1
2
#include <functional>
#include <future> 


reference:
https://en.cppreference.com/w/cpp/utility/functional/bind
https://en.cppreference.com/w/cpp/thread/async

more friendly reference:
http://www.cplusplus.com/reference/future/async/
http://www.cplusplus.com/reference/functional/bind/
Last edited on
Very good!

Now, the problem is:
"invalid use of incomplete type 'class std::future<void>'"
Class:Intervalo;
object:_intervalo;
argument:intervalo.

I write:
 
async(bind(&Interface::mostraTemperatura,_interface, intervalo));
Note that since you are working with threads your intervalo variable needs to be thread safe, otherwise your program will crash.

for example:
1
2
3
4
5
6
7
std::atomic<double> intervalo;

// to read value use:
intervalo.load();

// to write value use:
intervalo.write();


Otherwise if your shared variable is not trivial, you should not use std::atomic but instead use std::mutex

for example:
1
2
3
4
5
6
7
8
9
10
11
12
double intervalo;
std::mutex mMutex;

// read
mMutext.lock();
auto var = intervalo
mMutext.unlock();

// write
mMutext.lock();
intervalo = 4.33;
mMutext.unlock();


headers you need:
1
2
#include <mutex>
#include <atomic> 


reference:
http://www.cplusplus.com/reference/atomic/atomic/atomic/
http://www.cplusplus.com/reference/mutex/mutex/
Last edited on
I write:

async(bind(&Interface::mostraTemperatura,_interface, intervalo));


Sorry that was my mistake!

try this, without std::bind:
async(std::launch::async, &Interface::mostraTemperatura,_interface, intervalo);
Last edited on
The errors now is:
"'mutex' was not declared in this scope";
invalid use of incomplete type 'class std::future<void>'

1
2
3
4
5
6
mutex mMutex;
	ListaEncadeada<Estado> lista;
	Interface _interface(n);
	c_clrscr();
	_interface.mostraTemperatura(intervalo);
	async(launch::async, &Interface::mostraTemperatura,_interface, intervalo);
I used the library mutex!
The errors now is:
invalid use of incomplete type 'class std::future<void>'
"'mutex' was not declared in this scope";


It's hard to tell what you did wrong without seeing the code, here are only suggestions.

note that std::async returns std::future object.

that means to retrieve the result of a thread (if you return a result) you need something like this:
1
2
auto ret = async(launch::async, &Interface::mostraTemperatura,_interface, intervalo);
auto result = ret.get(); // to get the result of a thread if you need it. 


your std::mutex variable need to be declared inside the class probably, or somewhere where all the threads can access it, that means it should be visible to all the threads that use it.

It all depends on how and where you use the result of async operation. in either case return value is std::future which has member get() to get the value, which blocks until thread is done.

also try not to forget including std headers where needed, ie. in your own headers.

maybe if you share more complete example code someone could give you more info.
Last edited on
Thanks for every replies! there are a limit for code, can I share with git for you look the problem?
send me a link, (either PM or here) I'll see if I have the time and will to make a commit.
I need your e-mail for share.
sorry, I'm not going to share my e-mail.

you can send me private message here in forums, click on my nick name and there you have an option on the left to "Send private message".

then simply input your github link.
Do you don't receive messages in private, you need config the site.
Here is some sample async code (which executes a member function asynchronously):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <string>
#include <ctime>
#include <sstream>
#include <thread>
#include <random>
#include <chrono>
#include <mutex>
#include <future>

std::mutex stdout_mutex ;

std::string label()
{
    std::ostringstream stm ;
    const std::time_t now = std::time(nullptr) ;
    stm << "thread #" << std::this_thread::get_id()
        << " at " << std::ctime( std::addressof(now) ) ;
    auto str = stm.str() ;
    str.pop_back() ;
    return str + " : " ;
}

struct Interface
{
    void mostraTemperatura( unsigned int interval_millisecs, int loop_cnt )
    {
        // simulkate a random temperature that was read
        static std::mt19937 rng( std::random_device{}() ) ;
        static std::uniform_real_distribution<double> random_temperature( 15.0, 45.0 ) ;

        const std::chrono::milliseconds sleep_time(interval_millisecs) ;
        while( loop_cnt-- > 0 )
        {
            {
                std::lock_guard<std::mutex> lock(stdout_mutex) ;
                std::cout << label() << random_temperature(rng)
                          << " Celsius\n" << std::flush ;
            }
            std::this_thread::sleep_for(sleep_time) ;
        }
    }
};

int main()
{
    Interface interface ;
    
    // std::launch::async: launch in a seperate thread
    auto future = std::async( std::launch::async, &Interface::mostraTemperatura,
                              std::addressof(interface), 1000, 10 ) ;

    for( int i = 0 ; i < 5 ; ++i )
    {
        {
            std::lock_guard<std::mutex> lock(stdout_mutex) ;
            std::cout << label() << " in main\n" << std::flush ;
        }
        std::this_thread::sleep_for( std::chrono::milliseconds(1500) ) ;
    }

    {
        std::lock_guard<std::mutex> lock(stdout_mutex) ;
        std::cout << label() << " waiting for async execution to finish\n" << std::flush ;
    }
    future.wait() ; // wait for the async execution to finish
    std::cout << "the async execution has finished\n" ;
    
    // rest of main
}

http://coliru.stacked-crooked.com/a/c91018a599c6fca7
https://rextester.com/FITFG21980
Topic archived. No new replies allowed.