Multiple threads passing parameter - c++

Having:
class CPU() {};
void executable() {} , inside CPU; this function is executed by a thread.
void executable(){
while(run) { // for thread
cout << "Printing the memory:" << endl;
for (auto& t : map) {
cout << t.first << " " << t.second << "\n";
}
}
}
Need to instantiate 5 threads that execute executable() function:
for (int i = 0; i < 5; i++)
threads.push_back(thread(&CPU::executable, this)); //creating threads
cout << "Synchronizing all threads...\n";
for (auto& th : threads) th.join(); //waits for all of them to finish
Now, I want to create:
void executable0 () {
while(run) {
cout << "Printing the memory:" << endl;
for (auto& t : map) {
cout << t.first << " " << t.second << "\n";
}
}
}
void executable1 () {....}
to executable4() {....} // using that five threads that I`ve done above.
How could I do? Initialize or using std:thread constructor?
Can someone give me an example to understand this process.
Thanks & regards!

Following Some programmer dude's comment, I would also advise using a standard container of std::function:
#include <iostream>
#include <thread>
#include <map>
#include <functional>
#include <vector>
class CPU {
std::vector<std::function<void()>> executables{};
std::vector<std::thread> threads{};
public:
CPU() {
executables.emplace_back([](){
std::cout << "executable0\n";
});
executables.emplace_back([](){
std::cout << "executable1\n";
});
executables.emplace_back([](){
std::cout << "executable2\n";
});
}
void create_and_exec_threads() {
for(const auto executable : executables) {
threads.emplace_back([=](){ executable(); });
}
for(auto& thread : threads) {
thread.join();
}
}
};
We create a vector holding three callbacks, which will be used to initialise threads and start them inside create_and_exec_threads method.
Please do note that, as opposed to the comment in your example, creating a std::thread with a callback passed to its contructor will not only construct the thread, but also it will start it immediately.
Additionally, the std::thread::join method does not start the the thread. It waits for it to finish.

Related

How to understand destructor of scoped_lock?Does cppreference make a mistake?

~scoped_lock()
{ std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); }
How to understand [](auto&... __m) { (__m.unlock(), ...);? I don't understand the ... in lambda and I don't know how this implement release mutexes in reverse order.
Just as #HolyBlackCat say,
(__m.unlock(), ...) means (__m1.unlock(),(__m2.unlock(), (__m3.unlock(), (...)))), but it does not implement unlocking in reverse order.
In cppreference.com :
When control leaves the scope in which the scoped_lock object was created, the scoped_lock is destructed and the mutexes are released, in reverse order.
I make an experiment to confirm this as follows:
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
class mymutex : public std::mutex {
public:
void lock() {
std::mutex::lock();
std::cout << "mutex " << _i << " locked" << std::endl;
}
mymutex(int i): _i(i){}
bool try_lock() {
bool res = std::mutex::try_lock();
if (res) {
std::cout << "mutex " << _i << " try locked" << std::endl;
}
return res;
}
void unlock() {
std::mutex::unlock();
std::cout << "mutex " << _i << " unlocked" << std::endl;
}
private:
int _i;
};
class Speaking {
private:
int a;
mymutex my1;
mymutex my2;
mymutex my3;
public:
Speaking() : a(0), my1(1), my2(2), my3(3){};
~Speaking() = default;
void speak_without_lock();
void speak_with_three_lock();
};
void Speaking::speak_without_lock() {
std::cout << std::this_thread::get_id() << ": " << a << std::endl;
a++;
}
void Speaking::speak_with_three_lock()
{
std::scoped_lock<mymutex, mymutex, mymutex> scoped(my1, my2, my3);
speak_without_lock();
}
int main() {
Speaking s;
s.speak_with_three_lock();
return 0;
}
mutex 1 locked
mutex 2 try locked
mutex 3 try locked
1: 0
mutex 1 unlocked
mutex 2 unlocked
mutex 3 unlocked
So does cppreference make a mistake?
I believe that cppreference.com is incorrect in this detail. C++17 says:
~scoped_lock();
Effects: For all i in [0, sizeof...(MutexTypes)), get(pm).unlock()
which implies that the locks are released in the same order they were taken.
Note that to prevent deadlock, releasing locks in the reverse order of acquiring them is not necessary - it's only necessary to always acquire them in the same order.

Asynchronous HTTP requests with co_await

I have multiple std::functions that are called on the main thread (not on different threads) in my app (as the result of an asynchronous HTTP requests), for example:
namespace model { struct Order{}; struct Trade{};}
std::function<void (std::string)> func1 = [](std::string http_answer)
{
std::vector<model::Order> orders = ParseOrders(http_answer);
std::cout << "Fetched " << orders.size() << " open/closed orders.");
}
std::function<void (std::string)> func2 = [](std::string http_answer)
{
std::vector<model::Trade> trades = ParseTrades(http_answer);
std::cout << "Fetched " << trades.size() << " trades.");
}
How to call process_result when the both func1 and func2 have parsed HTTP answers?
auto process_result = [](std::vector<model::Order> orders, std::vector<model::Trades> trades)
{
std::cout << "Matching orders and trades.";
};
Is there some solution with co_await or something like this?
You need some kind of synchronization point. Have not used co_await so far so this might not be what you are looking for, however in c++17 I'd go for a std::promise / std::future, maybe like this:
#include <iostream>
#include <functional>
#include <future>
std::promise<std::string> p1;
std::function<void (std::string)> func1 = [](std::string http_answer)
{
// std::vector<model::Order> orders = ParseOrders(http_answer);
// std::cout << "Fetched " << orders.size() << " open/closed orders.");
p1.set_value(http_answer);
};
std::promise<std::string> p2;
std::function<void (std::string)> func2 = [](std::string http_answer)
{
// std::vector<model::Trade> trades = ParseTrades(http_answer);
// std::cout << "Fetched " << trades.size() << " trades.");
p2.set_value(http_answer);
};
int main () {
// whenever that happens...
func1("foo");
func2("bar");
// synchronize on func1 and func2 finished
auto answer1 = p1.get_future().get();
auto answer2 = p2.get_future().get();
auto process_result = [&](/* std::vector<model::Order> orders, std::vector<model::Trades> trades */)
{
std::cout << "Matching orders and trades... " << answer1 << answer2;
};
process_result();
return 0;
}
http://coliru.stacked-crooked.com/a/3c74f00125999fb6
https://en.cppreference.com/w/cpp/thread/future

std::jthread runs a member function from another member function

Here is my code:
#include <iostream>
#include <zconf.h>
#include <thread>
class JT {
public:
std::jthread j1;
JT() {
j1 = std::jthread(&JT::init, this, std::stop_token());
}
void init(std::stop_token st={}) {
while (!st.stop_requested()) {
std::cout << "Hello" << std::endl;
sleep(1);
}
std::cout << "Bye" << std::endl;
}
};
void init_2(std::stop_token st = {}) {
while (!st.stop_requested()) {
std::cout << "Hello 2" << std::endl;
sleep(1);
}
std::cout << "Bye 2" << std::endl;
}
int main() {
std::cout << "Start" << std::endl;
JT *jt = new JT();
std::jthread j2(init_2);
sleep(5);
std::cout << "Finish" << std::endl;
}
Here is the output:
Start
Hello
Hello 2
Hello
Hello 2
Hello
Hello 2
Hello
Hello 2
Hello
Hello 2
Finish
Bye 2
Hello
The problem is I could get Bye 2 message but not Bye message.
I know the passed stop_token variable results in this problem but I do not know how to pass it to a member function inside another member function.
If I'm understanding the problem correctly (my understanding being that for std::jthread(&JT::init, this) jthread wants to call JT::init(std::stop_token st, this), which isn't going to work), you probably want to use std::bind_front to give it a Callable that works.
e.g.
JT() {
j1 = std::jthread(std::bind_front(&JT::init, this));
}
According to the useful comments, I have rewritten the class code as below:
class JT {
public:
std::jthread j1;
JT() {
j1 = std::jthread(&JT::init, this);
}
void init() {
auto st = j1.get_stop_token();
while (!st.stop_requested()) {
std::cout << "Hello" << std::endl;
sleep(1);
}
std::cout << "Bye" << std::endl;
}
};
You must get the stop_token on the fly through auto st = j1.get_stop_token();.
And the revised main function:
int main() {
std::cout << "Start" << std::endl;
JT *jt = new JT();
// auto jt = std::make_unique<JT>();
std::jthread j2(init_2);
sleep(5);
std::cout << "Finish" << std::endl;
delete jt;
}
You need to delete the class object directly or use RAII (like smart pointers).
The std::stop_token must be received as parameter by the JT::init function, during the thread construction. You can use either std::bind
j1 = std::jthread{ std::bind(&JT::init, this, std::placeholders::_1) };
or, more simpler, std::bind_front as in #Hasturkun answer.
Note
Obtaining the std::stop_token after the thread has been constructed will eventually result in missing the stop request, as demonstrated bellow:
#include <thread>
#include <iostream>
using namespace std::chrono_literals;
class JT {
public:
std::jthread j1;
JT() {
j1 = std::jthread(&JT::init, this);
}
~JT() {
j1.request_stop();
j1.join();
}
void init() {
auto st = j1.get_stop_token();
while (!st.stop_requested()) {
std::this_thread::sleep_for(1ms);
std::cout << "Hello" << std::endl;
}
std::cout << "Bye" << std::endl;
}
};
int main() {
std::cout << "Start" << std::endl;
for (int i = 0; i < 1000; i++) {
JT jt;
std::this_thread::sleep_for(5ms);
}
}
Which results in:
Start
Hello
Bye
Hello
Bye
Hello
Hello
Hello
Hello
Hello
Hello
....
and program never ending. I've tested on release with gcc 12.1.0 and msvc (VS 2019 16.11.5).

How can I keep separate variable copy for same class object's member function?

I have a class object obj1 and I am trying to call a member function sdf_write from 2-separate-threads.
There is a static variable wr_count inside the member-function.
The issue is: when I run both threads, the wr_count value is being shared between both threads.
For e.g. thread_1 runs 8-times and makes the wr_count=8 but when thread_2 starts it makes the wr_count=9. I want thread_2 to start counting from "1" not from the last value of thread_1.
Here is my code:
#include <iostream>
#include <stdio.h>
#include <thread>
#include "sdf_func.hpp"
#include <vector>
using namespace std;
int main() {
sdf obj1;
std::thread t1([&obj1](){
for (int i=0; i<30; i++) {
while (!obj1.sdf_write(10));
};
});
t1.detach();
std::thread t2([&obj1](){
for (int i=0; i<30; i++) {
while (!obj1.sdf_write(10));
};
});
t2.join();
cout << "done: " << obj1.done << endl;
// cout << "done: " << obj2.done << endl;
// cout << "wr_count: " << obj1.wr_count << endl;
return 0;
}
// This is sdf_func/////////////////
#include <iostream>
#include <stdio.h>
#include <thread>
#include <mutex>
using namespace std;
class sdf {
public:
int done;
std::mutex mutex;
sdf() : done(0){};
void increment() {
std::lock_guard<std::mutex> guard(mutex);
++done;
}
bool sdf_write (auto size) {
static int wr_count = 0;
if (wr_count == size) {
wr_count = 0;
increment();
//cout << "done : " << done;
return false;
}
wr_count++;
cout << wr_count << "--" << std::this_thread::get_id() << endl;
return true;
}
};
This is a perfect job for the thread_local storage duration, which is a keyword introduced from C++11.
thread_local int wr_count;
Essentially, you get a separate static instance of wr_count per thread; each one is initialised to 0.
Reference: http://en.cppreference.com/w/cpp/keyword/thread_local

Object changing after storing and retrieving from unordered_map

Consider the following code. I want to use mutex_by_name() to create and retrieve mutexes. The lock is not a real lock, but should do its job with a one second gap.
Expected output is that m4.lock() fails aka prints lock FAILED because _locked is already set to true. But it does lock. I'm new to C++ and pretty sure I'm missing something obvious. Can you please explain how to implement that correctly.
#include <iostream>
#include <string>
#include <unordered_map>
#include <unistd.h>
class Mutex {
private:
int _id;
bool _locked = false;
void status(std::string s) {
std::cout << _id << " " << name << " " << s << " " << std::endl;
}
public:
const std::string name;
Mutex(std::string name): name(name) {
static int id = 0;
_id = id++;
status("created");
}
Mutex(const Mutex& m): _id(m._id), _locked(m._locked), name(m.name) {
status("copy-constructed");
}
Mutex(Mutex&& m) = delete;
void operator=(Mutex&) = delete;
~Mutex() {
status("deleted");
}
void lock() {
// YES, THIS IS NOT A REAL AND SAFE LOCK
if (!_locked) {
_locked = true;
status("locked");
} else {
status("lock FAILED");
}
}
};
std::unordered_map<std::string, Mutex> mutexe;
Mutex& mutex_by_name(std::string name) {
mutexe.emplace(name, Mutex(name));
auto found = mutexe.find(name);
return found->second;
}
using namespace std;
int main() {
cout << "# 1" << endl;
Mutex m1 = mutex_by_name("hello");
m1.lock();
sleep(1);
cout << "# 2" << endl;
Mutex m4 = mutex_by_name("hello");
m4.lock();
sleep(1);
}
You have to problems. First of all, you're not declaring m1 and m4 as references, and they shall be so.
Secondly, code style :).
So, this shall solve it:
Mutex &m1 = mutex_by_name("hello");
//...
Mutex &m4 = mutex_by_name("hello");
In main you need to make m1 and m4 references (Mutex &m1). Right now they are copies and thus aren't updating the value in the unordered map.