I would like to apply as simple mutex as possible.
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <algorithm>
#include <mutex>
using namespace std;
int sum;
static mutex m;
void addValue(int value)
{
m.lock();
sum += value;
m.unlock();
}
int main()
{
int counter1 = 0;
int counter2 = 0;
for (int i = 0; i < 100; i++)
{
thread t1(addValue, 100);
thread t2(addValue, 200);
if (sum == 300)
{
counter1++;
}
else
{
counter2++;
}
sum = 0;
t1.join();
t2.join();
}
cout << counter1 << endl;
cout << counter2 << endl;
}
Unfortunately above mentioned code doesn't work as expected. I expect that:
a) sum is always equal to 300
b) counter1 is always 100
c) counter2 is always 0
What is wrong?
EDIT:
When I debug the sum variable in the else condition, I see values like:
200, 400, 100, and even 0 (I assume that addition didn't even happen).
C++ mutex doesn't work - synchronization fails
Why does everyone learning this stuff for the first time assume the tried-and-tested synchronization primitives that work for everyone else are broken, and not their assumptions?
The mutex is fine. Your mental model is broken. This should be your starting assumption.
I expect that:
sum is always equal to 300
That would be the case if you joined both threads before checking the value. But you haven't done that, so you're doing an entirely un-sychronized read of sum while two other threads are possibly mutating it. This is a data race. A mutex doesn't protect your data unless you always use the mutex when accessing the data.
Let's say we make the minimal change so sum is always protected:
thread t1(addValue, 100); // a
thread t2(addValue, 200); // b
m.lock();
if (sum == 300) // c
{
counter1++;
}
else
{
counter2++;
}
sum = 0;
m.unlock();
now some of the available orderings are:
abc - what you expected (and what would be guaranteed if you joined both threads before reading sum)
acb - you read 100 at line c, increment counter2, and the second thread increments sum to 300 after you read it (but you never see this)
cab - you read 0 immediately, before the two threads have even been scheduled to run
bca - you read 200, it's later incremented to 300 after you checked
etc.
every permutation is permitted, unless you make some effort to explicitly order them
It is working as intended, the problem is that you didn't expected that "time" will not be the same for all 3 threads and you dismist the obvious thing that one thread starts before the other, this clearly adds an avantage, even more if it only needs to do is loop 100 times a increment.
#include <iostream>
#include <thread>
#include <mutex>
bool keep_alive;
void add_value_mutex(std::mutex * mx, int * trg, int value) {
while (keep_alive){
mx->lock();
(*trg) += value;
mx->unlock();
}
}
int main(){
std::thread thread_1;
std::thread thread_2;
int count_targ = 2000;
int * counter_1 = new int(0);
int * counter_2 = new int(0);
/* --- */
std::mutex mx_1;
std::mutex mx_2;
keep_alive = true;
thread_1 = std::thread(add_value_mutex, &mx_1, counter_1, 1);
thread_2 = std::thread(add_value_mutex, &mx_2, counter_2, 1);
while(1){
if (mx_1.try_lock()){
if (count_targ <= * counter_1){
mx_1.unlock();
break;
}
mx_1.unlock();
}
if (mx_2.try_lock()){
if (count_targ <= * counter_2){
mx_2.unlock();
break;
}
mx_2.unlock();
}
}
keep_alive = false;
thread_1.join();
thread_2.join();
std::cout << "Thread 1 (independent mutex) -> " << * counter_1 << std::endl;
std::cout << "Thread 2 (independent mutex) -> " << * counter_2 << std::endl;
/* --- */
keep_alive = true;
(*counter_1) = 0;
(*counter_2) = 0;
std::mutex mx_s;
thread_1 = std::thread(add_value_mutex, &mx_s, counter_1, 1);
thread_2 = std::thread(add_value_mutex, &mx_s, counter_2, 1);
while(1){
if (mx_s.try_lock()){
if (count_targ <= * counter_1 || count_targ <= * counter_2){
mx_s.unlock();
break;
}
mx_s.unlock();
}
}
std::cout << "Thread 1 (shared mutex) -> " << * counter_1 << std::endl;
std::cout << "Thread 2 (shared mutex) -> " << * counter_2 << std::endl;
keep_alive = false;
thread_1.join();
thread_2.join();
delete counter_1;
delete counter_2;
return 0;
}
If you want another example of mine that measures the time a thread is waiting check this one
Related
I wrote a simple program to test out the performance of std::shared_mutex across a number of threads looping lock_shared(). But from the result, it doesn't seems to scale with more threads added, which doesn't really make sense to me.
You may argue it's because the stopFlag limiting the performance, so the second for loop a test for increment a local counter, which is almost perfect scaling in the beginning
The result in the comments are compiled with MSVC with Release flag.
int main()
{
const auto threadLimit = std::thread::hardware_concurrency() - 1; //for running main()
struct SharedMutexWrapper
{
std::shared_mutex mut;
void read()
{
mut.lock_shared();
mut.unlock_shared();
}
};
/*Testing shared_mutex */
for (auto i = 1; i <= threadLimit; ++i)
{
std::cerr << "Testing " << i << " threads: ";
SharedMutexWrapper test;
std::atomic<unsigned long long> count = 0;
std::atomic_bool stopFlag = false;
std::vector<std::thread> threads;
threads.reserve(i);
for (auto j = 0; j < i; ++j)
threads.emplace_back([&] {unsigned long long local = 0; while (!stopFlag) { test.read(); ++local; } count += local; });
std::this_thread::sleep_for(std::chrono::seconds{ 1 });
stopFlag = true;
for (auto& thread : threads)
thread.join();
std::cerr << count << '\n';
}
/*
Testing 1 threads: 60394076
Testing 2 threads: 39703889
Testing 3 threads: 23461029
Testing 4 threads: 16961003
Testing 5 threads: 12750838
Testing 6 threads: 12227898
Testing 7 threads: 12245818
*/
for (auto i = 1; i <= threadLimit; ++i)
{
std::cerr << "Testing " << i << " threads: ";
std::atomic<unsigned long long> count = 0;
std::atomic_bool stopFlag = false;
std::vector<std::thread> threads;
threads.reserve(i);
for (auto j = 0; j < i; ++j)
threads.emplace_back([&] {unsigned long long local = 0; while (!stopFlag) ++local; count += local; });
std::this_thread::sleep_for(std::chrono::seconds{ 1 });
stopFlag = true;
for (auto& thread : threads)
thread.join();
std::cerr << count << '\n';
}
/*
Testing 1 threads: 3178867276
Testing 2 threads: 6305783667
Testing 3 threads: 9388659151
Testing 4 threads: 12472666861
Testing 5 threads: 15230810694
Testing 6 threads: 18130479890
Testing 7 threads: 20151074046
*/
}
Placing a read lock on a shared mutex modifies the state of that mutex. All your threads do nothing but try to change the state of the same object, the shared mutex. So of course this code is going to scale poorly.
The point of a shared mutex is to allow accesses to shared data that is not modified to scale. You have no accesses to shared data that is not modified. So you aren't measuring any of the beneficial properties of a shared mutex here.
Hello I am trying to write a C++ multithreaded program using POSIX thread library to find the number of prime numbers between 1 and 10,000,000 (10 million) and find out how many microseconds it takes...
Creating my threads and running them works completely fine, however I feel as if there is an error found in my Prime function when determining if a number is prime or not...
I keep receiving 78496 as my output, however I desire 664579. Below is my code. Any hints or pointers would be greatly appreciated.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <sys/time.h> //measure the execution time of the computations
using namespace std;
//The number of thread to be generated
#define NUMBER_OF_THREADS 4
void * Prime(void* index);
long numbers[4] = {250000, 500000, 750000, 1000000};
long start_numbers[4] = {1, 250001, 500001, 750001};
int thread_numbers[4] = {0, 1, 2, 3};
int main(){
pthread_t tid[NUMBER_OF_THREADS];
int tn;
long sum = 0;
timeval start_time, end_time;
double start_time_microseconds, end_time_microseconds;
gettimeofday(&start_time, NULL);
start_time_microseconds = start_time.tv_sec * 1000000 + start_time.tv_usec;
for(tn = 0; tn < NUMBER_OF_THREADS; tn++){
if (pthread_create(&tid[tn], NULL, Prime, (void *) &thread_numbers[tn]) == -1 ) {
perror("thread fail");
exit(-1);
}
}
long value[4];
for(int i = 0; i < NUMBER_OF_THREADS; i++){
if(pthread_join(tid[i],(void **) &value[i]) == 0){
sum = sum + value[i]; //add four sums together
}else{
perror("Thread join failed");
exit(-1);
}
}
//get the end time in microseconds
gettimeofday(&end_time, NULL);
end_time_microseconds = end_time.tv_sec * 1000000 + end_time.tv_usec;
//calculate the time passed
double time_passed = end_time_microseconds - start_time_microseconds;
cout << "Sum is: " << sum << endl;
cout << "Running time is: " << time_passed << " microseconds" << endl;
exit(0);
}
//Prime function
void* Prime(void* index){
int temp_index;
temp_index = *((int*)index);
long sum_t = 0;
for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){
for (int j=2; j*j <= i; j++)
{
if (i % j == 0)
{
break;
}
else if (j+1 > sqrt(i)) {
sum_t++;
}
}
}
cout << "Thread " << temp_index << " terminates" << endl;
pthread_exit( (void*) sum_t);
}```
This is because, you used 10^6 instead of 10^7.
Also, added some corner cases for numbers 1, 2 and 3:
//Prime function
void* Prime(void* index){
int temp_index;
temp_index = *((int*)index);
long sum_t = 0;
for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){
// Corner cases
if(i<=1)continue;
if (i <= 3){
sum_t++;
continue;
}
for (int j=2; j*j <= i; j++)
{
if ((i % j == 0) || (i %( j+2))==0 )
{
break;
}
else if (j+1 > sqrt(i)) {
sum_t++;
}
}
}
cout << "Thread " << temp_index << " terminates" << endl;
pthread_exit( (void*) sum_t);
}
I tested your code with correct number and got the correct number of primes as output:
Thread 0 terminates
Thread 1 terminates
Thread 2 terminates
Thread 3 terminates
Sum is: 664579
Running time is: 4.69242e+07 microseconds
Thanks to #chux - Reinstate Monica for pointing this out
Along with taking 10^7 as the numbers divided in thread instead of setting the limit as 10^6 ,a number of other small scale errors are there and a number of optimizations could be made -
First of all start numbers could be from 2 itself
long start_numbers[4] = {2, 2500001, 5000001, 7500001};
sum_t++ in your code may not work on edge cases. It is better to follow the following algorithm for calculating Prime function
bool flag = false;
for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){
flag = false;
for (long j=2; j*j <= i; j++){
if (i % j == 0 )
{
flag = true;
break;
}
}
if(!flag)
sum_t++;
}
After these 2 operations i am getting the result as
Thread 0 terminates
Thread 1 terminates
Thread 2 terminates
Thread 3 terminates
Sum is: 664579
Running time is: 6.62618e+06 microseconds
edit:
( Note : in this case j is taken as long datatype but it could work as well with int in this 'example' since the tested compiler takes int as 32 bits long)
I wrote a program that searches for primes:
#include <iostream>
#include <fstream>
#include <chrono>
typedef std::chrono::high_resolution_clock Clock;
using namespace std;
int main() {
int p;
int x = 1;
int b;
int a[1000000];
bool n = false;
a[0] = 2;
a[1] = 3;
auto t1 = Clock::now();
ofstream outfile;
outfile.open("p.txt");
for (p = 3; p < 7500000; p = p + 2)
{
for (b = 0; b <= x && n == 0; b++)
{
if (p % a[b / 2] == 0)
{
n = true;
}
}
if (n == false)
{
cout << p << endl;
outfile << p << endl;
x++;
a[x] = p;
}
else
{
n = false;
}
}
auto t2 = Clock::now();
std::cout
<< std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count()
<< " nanoseconds" << std::endl;
outfile.close();
}
Initially for the loop increment I had p++, but I changed that to p=p+2 because all primes essentially are odd and even numbers don't need to be checked. Problem is when I benchmarked this, there was no difference in speed between the old and new code. So what is the bottleneck in the process, if checking all the numbers is no different than checking half? And is there a better way to approach this?
Your outer loop skips half the numbers. But your inner loop tests every number twice. So you give up all your gains.
If you don't see that your inner loop does everything twice, consider that a[b/2] is the same when b is 1 as it is when b is 0.
It's this line:
for(b=0; b<=x && n==0; b++)
Once n=true; executes, the b loop exits because of the && n==0 condition. This happens with the very first test: every even number is divisible by two, which is a[0]. So for even numbers (that you include if you use p++ instead of p=p+2) the inner loop is very quick, much quicker than for a typical odd number. This explains why including them makes so little difference.
I have some functions that check for prime numbers in a given range and output the results to a text file. The function also requires the user to input how many threads the function will use.
#include "threads.h"
#include <thread>
#include <ctime>
bool isPrime(int n)
{
if (n == 2)
return true;
int i = 2;
while (i < n)
if (n % i++ == 0)
return false;
return true;
}
void writePrimesToFile(int begin, int end, ofstream& file)
{
for (int i = (begin % 2 == 0 ? begin + 1 : begin); i <= end; i += 2)
if (isPrime(i))
file << i << endl;
}
void callWritePrimesMultipleThreads(int begin, int end, string filePath, int N)
{
ofstream file(filePath);
if (file.is_open())
{
clock_t time = clock();
for (int i = 0; i < N; i++)
{
int _begin = ((end - begin) / N) * i,
_end = ((end - begin) / N) * (i + 1);
thread t(writePrimesToFile, ref(_begin), ref(_end), ref(file));
t.join();
}
cout << "Time elpased: " << (double(clock() - time) / CLOCKS_PER_SEC) << endl;
file.close();
}
else
cout << "Can't open file!" << endl;
}
Here's the main:
#include "threads.h"
int main()
{
callWritePrimesMultipleThreads(0, 1000, "primes.txt", 10);
return 0;
}
I want to know, for which value of N, the amount of threads, the program will run the best.
An optimal solution to this problem would be to start N threads, each running the same function, that increments a shared counter (using InterlockedIncrement, for thread-safety), and calculates whether or not it is prime.
If you do this, and set N to the number of cores in your machine, you will get the optimal 100% CPU consumption, with zero context switches.
Regarding the output, notice that you can't safe write to one output file without locking (which you want to avoid). Instead, I would collect the prime numbers in an array or vectors (one vector for each thread), and eventually merge them into one vector, sort them and then write to file.
I am working on a proof of concept test program for a game where certain actions are threaded and information is output to the command window for each thread. So far I have gotten the basic threading process to work but it seems that the couting in my called function is not being written for each thread and instead each thread is overwriting the others output.
The desired or expected output is that each thread will output the information couted within the mCycle function of mLaser. Essentially this is meant to be a timer of sorts for each object counting down the time until that object has completed its task. There should be an output for each thread, so if five threads are running there should be five counters counting down independently.
The current output is such that each thread is outputting its own information with in the same space which then overwrites what another thread is attempting to output.
Here is an example of the current output of the program:
Time until cycle Time until cycle 74 is complete: 36 is complete:
92 seconds 2 seconds ress any key to continue . . .
You can see the aberrations where numbers and other text are in places they should not be if you examine how the information is couted from mCycle.
What should be displayed is more long these lines:
Time until cycle 1 is complete:
92 seconds
Time until cycle 2 is complete:
112 seconds
Time until cycle 3 is complete:
34 seconds
Cycle 4 has completed!
I am not sure if this is due to some kind of thread locking going on due to how my code is structured or just an oversight in my coding for the output. If I could get a fresh pair of eyes to look over the code and point anything out that could be the fault I would appreciate it.
Here is my code, it should be compilable in any MSVS 2013 install (no custom libraries used)
#include <iostream>
#include <Windows.h>
#include <string>
#include <vector>
#include <random>
#include <thread>
#include <future>
using namespace std;
class mLaser
{
public:
mLaser(int clen, float mamt)
{
mlCLen = clen;
mlMAmt = mamt;
}
int getCLen()
{
return mlCLen;
}
float getMAmt()
{
return mlMAmt;
}
void mCycle(int i1, int mCLength)
{
bool bMCycle = true;
int mCTime_left = mCLength * 1000;
int mCTime_start = GetTickCount(); //Get cycle start time
int mCTime_old = ((mCTime_start + 500) / 1000);
cout << "Time until cycle " << i1 << " is complete: " << endl;
while (bMCycle)
{
cout << ((mCTime_left + 500) / 1000) << " seconds";
bool bNChange = true;
while (bNChange)
{
//cout << ".";
int mCTime_new = GetTickCount();
if (mCTime_old != ((mCTime_new + 500) / 1000))
{
//cout << mCTime_old << " " << ((mCTime_new+500)/1000) << endl;
mCTime_old = ((mCTime_new + 500) / 1000);
mCTime_left -= 1000;
bNChange = false;
}
}
cout << " \r" << flush;
if (mCTime_left == 0)
{
bMCycle = false;
}
}
cout << "Mining Cycle " << i1 << " finished" << endl;
system("Pause");
return true;
}
private:
int mlCLen;
float mlMAmt;
};
string sMCycle(mLaser ml, int i1, thread& thread);
int main()
{
vector<mLaser> mlasers;
vector<thread> mthreads;
future<string> futr;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> laser(1, 3);
uniform_int_distribution<> cLRand(30, 90);
uniform_real_distribution<float> mARand(34.0f, 154.3f);
int lasers;
int cycle_time;
float mining_amount;
lasers = laser(gen);
for (int i = 0; i < lasers-1; i++)
{
mlasers.push_back(mLaser(cLRand(gen), mARand(gen)));
mthreads.push_back(thread());
}
for (int i = 0; i < mlasers.size(); i++)
{
futr = async(launch::async, [mlasers, i, &mthreads]{return sMCycle(mlasers.at(i), i + 1, mthreads.at(i)); });
//mthreads.at(i) = thread(bind(&mLaser::mCycle, ref(mlasers.at(i)), mlasers.at(i).getCLen(), mlasers.at(i).getMAmt()));
}
for (int i = 0; i < mthreads.size(); i++)
{
//mthreads.at(i).join();
}
//string temp = futr.get();
//float out = strtof(temp.c_str(),NULL);
//cout << out << endl;
system("Pause");
return 0;
}
string sMCycle(mLaser ml, int i1, thread& t1)
{
t1 = thread(bind(&mLaser::mCycle, ref(ml), ml.getCLen(), ml.getMAmt()));
//t1.join();
return "122.0";
}
Although writing from multiple threads concurrently to std::cout has to be data race free, there is no guarantee that concurrent writes won't be interleaved. I'm not sure if one write operation of one thread can be interleaved with one write operation from another thread but they can certainly be interleaved between write operations (I think individual outputs from different threads can be interleaved).
What the standard has to say about concurrent access to the standard stream objects (i.e. std::cout, std::cin, etc.) is in 27.4.1 [iostream.objects.overview] paragraph 4:
Concurrent access to a synchronized (27.5.3.4) standard iostream object’s formatted and unformatted input (27.7.2.1) and output (27.7.3.1) functions or a standard C stream by multiple threads shall not result in a data race (1.10). [ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. —end note ]
If you want to have output appear in some sort of unit, you will need to synchronize access to std::cout, e.g., by using a mutex.
While Dietmar's answer is sufficient I decided to go a different, much more simple, route. Since I am creating instances of a class and I am accessing those instances in the threads, I chose to update those class' data during the threading and then called the updated data once the thread have finished executing.
This way I do not have to deal with annoying problems like data races nor grabbing output from async in a vector of shared_future. Here is my revised code in case anyone else would like to implement something similar:
#include <iostream>
#include <Windows.h>
#include <string>
#include <vector>
#include <random>
#include <thread>
#include <future>
using namespace std; //Tacky, but good enough fo a poc D:
class mLaser
{
public:
mLaser(int clen, float mamt, int time_left)
{
mlCLen = clen;
mlMAmt = mamt;
mCTime_left = time_left;
bIsCompleted = false;
}
int getCLen()
{
return mlCLen;
}
float getMAmt()
{
return mlMAmt;
}
void setMCOld(int old)
{
mCTime_old = old;
}
void mCycle()
{
if (!bIsCompleted)
{
int mCTime_new = GetTickCount(); //Get current tick count for comparison to mCOld_time
if (mCTime_old != ((mCTime_new + 500) / 1000)) //Do calculations to see if time has passed since mCTime_old was set
{
//If it has then update mCTime_old and remove one second from mCTime_left.
mCTime_old = ((mCTime_new + 500) / 1000);
mCTime_left -= 1000;
}
cur_time = mCTime_left;
}
else
{
mCTime_left = 0;
}
}
int getCTime()
{
return cur_time;
}
int getCTLeft()
{
return mCTime_left;
}
void mCComp()
{
bIsCompleted = true;
}
bool getCompleted()
{
return bIsCompleted;
}
private:
int mlCLen; //Time of a complete mining cycle
float mlMAmt; //Amoung of ore produced by one mining cycle (not used yet)
int cur_time; //The current time remaining in the current mining cycle; will be removing this as it is just a copy of mCTime_left that I was going to use for another possiblity to make this code work
int mCTime_left; //The current time remaining in the current mining cycle
int mCTime_old; //The last time that mCycle was called
bool bIsCompleted; //Flag to check if a mining cycle has already been accounted for as completed
};
void sMCycle(mLaser& ml, int i1, thread& _thread); //Start a mining cycle thread
//Some global defines
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> laser(1, 10); //A random range for the number of mlaser entities to use
uniform_int_distribution<> cLRand(30, 90); //A random time range in seconds of mining cycle lengths
uniform_real_distribution<float> mARand(34.0f, 154.3f); //A random float range of the amount of ore produced by one mining cycle (not used yet)
int main()
{
//Init some variables for later use
vector<mLaser> mlasers; //Vector to hold mlaser objects
vector<thread> mthreads; //Vector to hold threads
vector<shared_future<int>> futr; //Vector to hold shared_futures (not used yet, might not be used if I can get the code working like this)
int lasers; //Number of lasers to create
int cycle_time; //Mining cycle time
int active_miners = 0; //Number of active mining cycle threads (one for each laser)
float mining_amount; //Amount of ore produced by one mining cycle (not used yet)
lasers = laser(gen); //Get a random number
active_miners = lasers; //Set this to that random number for the while loop later on
//Create the mlaser objects and push them into the mlasers vector
for (int i = 0; i < lasers; i++)
{
int clength = cLRand(gen);
mlasers.push_back(mLaser(clength, mARand(gen), (clength * 1000)));
//Also push thread obects into mthreads for each laser object
mthreads.push_back(thread());
}
//Setup data for mining cycles
for (int i = 0; i < mlasers.size(); i++)
{
int mCTime_start = GetTickCount(); //Get cycle start time
mlasers.at(i).setMCOld(((mCTime_start + 500) / 1000));
}
//Print initial display for mining cycles
for (int i = 0; i < mlasers.size(); i++)
{
cout << "Mining Laser " << i + 1 << " cycle will complete in " << (mlasers.at(i).getCTLeft() + 500) / 1000 << " seconds..." << endl;
}
while (active_miners > 0)
{
for (int i = 0; i < mlasers.size(); i++)
{
//futr.push_back(async(launch::async, [mlasers, i, &mthreads]{return sMCycle(mlasers.at(i), i + 1, mthreads.at(i)); }));
async(launch::async, [&mlasers, i, &mthreads]{return sMCycle(mlasers.at(i), i + 1, mthreads.at(i)); }); //Launch a thread for the current mlaser object
//mthreads.at(i) = thread(bind(&mLaser::mCycle, ref(mlasers.at(i)), mlasers.at(i).getCLen(), mlasers.at(i).getMAmt()));
}
//Output information from loops
//cout << " \r" << flush; //Return cursor to start of line and flush the buffer for the next info
system("CLS");
for (int i = 0; i < mlasers.size(); i++)
{
if (mlasers.at(i).getCTLeft() != 0) //If mining cycle is not completed
{
cout << "Mining Laser " << i + 1 << " cycle will complete in " << (mlasers.at(i).getCTLeft() + 500) / 1000 << " seconds..." << endl;
}
else if (mlasers.at(i).getCTLeft() == 0) //If it is completed
{
if (!mlasers.at(i).getCompleted())
{
mlasers.at(i).mCComp();
active_miners -= 1;
}
cout << "Mining Laser " << i + 1 << " has completed its mining cycle!" << endl;
}
}
}
/*for (int i = 0; i < mthreads.size(); i++)
{
mthreads.at(i).join();
}*/
//string temp = futr.get();
//float out = strtof(temp.c_str(),NULL);
//cout << out << endl;
system("Pause");
return 0;
}
void sMCycle(mLaser& ml, int i1,thread& _thread)
{
//Start thread
_thread = thread(bind(&mLaser::mCycle, ref(ml)));
//Join the thread
_thread.join();
}