I want to create a counter that spawns another separate counter when it reaches a certain value. My counters have a target, some initial value, and an increment value. I am using a while loop to increment them.
Here is my non functional code, I want to call childWhileLoop()
when the main while loop reaches a value of 2. Right now childWhileLoop()
doesn't print anything since it terminates before starting it's own while loop.
I think this scenario is a good use for multithreading, but I would like to know how I could carry out this logic in C++ with the appropriate multithreading libraries.
#include <stdio.h>
#include <iostream>
using std::cout;
using std::endl;
void childWhileLoop() {
double number = 2;
double currentValue = 0.1;
while(currentValue < number) {
cout << currentValue << endl;
currentValue += 0.1;
}
}
int main(int argc, char const *argv[])
{
double largeNumber = 5;
double currentValue = 0.1;
while(currentValue < largeNumber) {
cout << currentValue << endl;
if(currentValue == 2) {
childWhileLoop();
}
currentValue += 0.1;
}
return 0;
}
First, if (currentValue == 2)
will not become true
(see Is floating-point math broken?) so you need to check if it's in an acceptable range instead. (1.99, 2.01)
will do for this.
Second, if you want childWhileLoop
to run in parallel with the main
loop, you could start it in a std::jthread
.
Example:
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
void childWhileLoop() {
double number = 2;
double currentValue = 0.1;
while (currentValue < number) {
std::cout << "child: " << currentValue << '\n';
currentValue += 0.1;
// std::this_thread::sleep_for(std::chrono::microseconds(1));
}
}
int main() {
std::vector<std::jthread> threads;
double largeNumber = 5;
double currentValue = 0.1;
while (currentValue < largeNumber) {
std::cout << currentValue << '\n';
if (currentValue > 1.99 && currentValue < 2.01) {
// run childWhileLoop in a thread:
threads.emplace_back(childWhileLoop);
}
currentValue += 0.1;
// std::this_thread::sleep_for(std::chrono::microseconds(1));
}
}
Note 1: You will likely still see all output from the main
loop before you see anything from the loop running in the thread because of how the scheduler works. If you add a very short sleep in both loops (std::this_thread::sleep_for(std::chrono::microseconds(1));
) you'll probably see them working in parallel.
Note 2: I used a std::vector<std::jthread>
in case you want to put more threads in there eventually.
The main
function, without auto-joining jthread
s, could look like this:
int main() {
std::vector<std::thread> threads; // note: thread instead of jthread
double largeNumber = 5;
double currentValue = 0.1;
while (currentValue < largeNumber) {
std::cout << currentValue << '\n';
if (currentValue > 1.99 && currentValue < 2.01) {
// run childWhileLoop in a thread:
threads.emplace_back(childWhileLoop);
}
currentValue += 0.1;
// std::this_thread::sleep_for(std::chrono::microseconds(1));
}
// without jthread, you need to join:
for(auto& thread : threads) {
thread.join();
}
}