Issues with \r and \n or Buffer Flushing - c++

I have read in multiple places that \n does not flush the buffer when used however in my code, which I will add at the end of this question, it seems to be doing just that or at least it seems that way from the output (maybe something else is going on in the background due to how I am executing my couts?).
Expected Output:
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
What I Get in the CLI:
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
Mining Laser 1 cycle will complete in x seconds...
Mining Laser 2 cycle will complete in x seconds...
Mining Laser 3 cycle will complete in x seconds...
Mining Laser 4 cycle will complete in x seconds...
What I want the output to do is remain in place, like those in the expected output example, and just update itself every the time loop in my code executes.
Here is my code:
#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;
}
int getCLen()
{
return mlCLen;
}
float getMAmt()
{
return mlMAmt;
}
void setMCOld(int old)
{
mCTime_old = old;
}
void mCycle()
{
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;
}
int getCTime()
{
return cur_time;
}
int getCTLeft()
{
return mCTime_left;
}
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
};
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, 3); //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...\n";
}
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
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...\n";
}
else //If it is completed
{
cout << "Mining Laser " << i + 1 << " has completed its mining cycle!\n";
active_miners -= 1;
}
}
}
/*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();
}
Per Ben Voigt, it seems that \r cannot be used in the way I am attempting to use it. Does anyone have any other suggestions apart from Matthew's suggestion of clsing the command window each update? Maybe something in Boost or something new to c++11?
Thanks.

You could try clearing the console after every execution
with something like system("cls");
here is a link to a post
[How can I clear console

Related

Adjusting the speed of 2 different object on console

I'm making a simple game like Google's Dinosaur Game. As you pass the obstacles, their speed increases as well as the Dino. What I wanna do is make Dino's speed constant while obstacles speed increases.
while (1)
{
if (GetAsyncKeyState(VK_SPACE) < 0 || action) // checking if the user press SPACE
{
if (!action) button = _getch();
if (button == VK_SPACE) // rest is making the dino move up and down.
{
action = 1;
if (loop < 6)
{
std::queue<Position> tempQue = dinoPos;
for (size_t i = 0; i < DINOSIZE; i++)
{
setCursor(dinoPos.front().x, dinoPos.front().y); dinoPos.pop();
std::cout << " ";
}
for (size_t i = 0; i < DINOSIZE; i++)
{
setCursor(tempQue.front().x, tempQue.front().y - 1);
tempQue.front().y -= 1;
dinoPos.push(tempQue.front());
tempQue.pop();
std::cout << "D";
}
}
loop++;
if (loop == 12)
{
loop = 0;
action = 0;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(speed)); // using this for speeding up the game
You don't want to use sleep_for. It can sleep for longer and offers no timing guarantees. What you want it a fixed update game loop. You can look in popular game engines to see how it's implemented.
But it boils down to the following pseudo-code:
//mainloop
// get a number of frame based on time.
// take a number of frame higher than expected frame rate. say 10 ms.
int frame = now() / frameDuration;
while(true)
{
int frameNow = now() / frameDuration;
while(frame != frameNow)
{
Update();
frame++;
}
render();
}
With the following update function: (pseudo-code again)
// there, you advance you object for a fixing duration, say 10 ms.
// just use different speed for each
Update()
{
obstacle.position += obstacleSpeed * frameDuration;
character.position += characterSpeed * frameDuration;
}

openMP Lack of Diminishing Returns with Higher Thread Count

My code right now has a loop which calls a Monte-Carlo function to calculate a simple integral (y=x, from 0 to 1) for multiple number of samples and writes the total time and integration value to a text file. Then the loop increments the number of threads and continues onward. Right now around 8 threads the time peaks around 2.6 seconds. The loop iterates upwards of 64 threads, and I see no slow down beyond .2 seconds, even sometimes a speed up.
For loop calling Monte-Carlo method, increment number of threads:
//this loop will iterate the main loop for a number of threads from 1 to 16
for (int j = 1; j <= 17; j++)
{
//tell user how many threads are running monte-carlo currently
cout << "Program is running " << number_threads << " thread(s) currently." << endl;
//reset values for new run
num_of_samples = 1;
integration_result = 0;
//this for loop will run throughout number of circulations running through monte-carlo
//and entering the data into the text folder
for (int i = 1; i <= iteration_num; i++)
{
//call monte carlo function to perform integration and write values to text
monteCarlo(num_of_samples, starting_x, end_x, number_threads);
//increase num of samples for next test round
num_of_samples = 2 * num_of_samples;
} //end of second for loop
//iterate num_threads
if (number_threads == 1)
number_threads = 2;
else if (number_threads >= 32)
number_threads += 8;
else if (number_threads >= 16)
number_threads += 4;
else
number_threads += 2;
} //end of for loop
Parallel portion for Monte-Carlo:
int num_threads;
double x, u, error_difference, fs = 0, integration_result = 0; //fs is a placeholder to hold added values of f(x)
vector< vector<double>> dataHolder(number_threads, vector<double>(1)); //this vector will hold temp values of each thread
//get start time for parallel block of code
double start_time = omp_get_wtime();
omp_set_dynamic(0); // Explicitly disable dynamic teams
omp_set_num_threads(number_threads); // Use 4 threads for all consecutive parallel regions
#pragma omp parallel default(none) private(x, u) shared(std::cout, end_x, starting_x, num_of_samples, fs, number_threads, num_threads, dataHolder)
{
int i, id, nthrds;
double temp = fs;
//define thread id and num of threads
id = omp_get_thread_num();
nthrds = omp_get_num_threads();
//initilialize random seed
srand(id * time(NULL) * 1000);
//if there is only one thread
if(id == 0)
num_threads = nthrds;
//this for loop will calculate a temp value for fs for each thread
for (int i = id; i < num_of_samples; i = i + nthrds)
{
//assign random number under integration from 0 to 1
u = fRand(0, 1); //random number between 0 and 1
x = starting_x + (end_x - starting_x) * u;
//this line of code is from Monte_Carlo Method by Alex Godunov (February 2007)
//calculuate y for reciporical value of x and add it to thread's local fs
temp += function(x);
}
//place temp inside vector dataHolder
dataHolder[id][0] = temp;
//no thread will go beyond this barrier until task is complete
#pragma omp barrier
//one thread will do this task
#pragma omp single
{
//add summations to calc fs
for(i = 0, fs = 0.0; i < num_threads; i ++)
fs += dataHolder[i][0];
} //implicit barrier here, wait for all tasks to be done
}//end of parallel block of code
After implementing the same sort of parallelization over a simple Monte-Carlo walk with light scattering, I was able to pick up on the diminished returns quite a bit. I think there is a lack of diminishing returns here due to the fact that the integration calculation being so simple, that the threads themselves have little to do separately, and thus their overhead is relatively little.
If anyone else has any other information that would prove useful to this problem, please feel free to post. Otherwise I will accept this as my answer.

Multithreading Timer and I/O in Console C++

I'm developing a game that has a word falling to the bottom of the screen and the user typing that word before it hits the bottom. So you'll be able to type input while the word is falling. Right now I have a timer that waits 5 seconds, prints the word, runs timer again, clears the screen, and prints the word down 10 units.
int main()
{
for (int i = 0; i < 6; i++)
{
movexy(x, y);
cout << "hello\n";
y = y + 10;
wordTimer();
}
}
Very basic I know. Which is why I thought multithreading would be a good idea so that way I could have the word falling while I still type input at the bottom. This is my attempt at that so far:
vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
threads.push_back(std::thread(task1, "hello\n"));
threads.push_back(std::thread(wordTimer));
}
for (auto& thread : threads) {
thread.join();
}
However this only prints hello 4 times to the screen, then prints 55, then prints hello again, then counts-down 3 more times. So any advice on how to correctly do this? I've already done research. Just a few of the links I checked out that didn't help:
Multithreaded console I/O
C++11 Multithreading: Display to console
Render Buffer on Screen in Windows
Threading console application in c++
Create new console from console app? C++
Console output from thread
https://msdn.microsoft.com/en-us/library/975t8ks0.aspx?f=255&MSPPError=-2147217396
http://www.tutorialspoint.com/cplusplus/cpp_multithreading.htm
EDIT:
Here is wordTimer()
int wordTimer()
{
_timeb start_time;
_timeb current_time;
_ftime_s(&start_time);
int i = 5;
for (; i > 0; i--)
{
cout << i << endl;
current_time = start_time;
while (elapsed_ms(&start_time, &current_time) < 1000)
{
_ftime_s(&current_time);
}
start_time = current_time;
}
cout << " 5 seconds have passed." << endl;
return 0;
}
this is also necessary for wordTimer()
unsigned int elapsed_ms(_timeb* start, _timeb* end)
{
return (end->millitm - start->millitm) + 1000 * (end->time - start->time);
}
and task1
void task1(string msg)
{
movexy(x, y);
cout << msg;
y = y + 10;
}
and void movexy(int x, int y)
void movexy(int column, int line)
{
COORD coord;
coord.X = column;
coord.Y = line;
SetConsoleCursorPosition(
GetStdHandle(STD_OUTPUT_HANDLE),
coord
);
}
Threads do not run in any particular order - the operating system can schedule them whenever it feels like it. Your code starts ten threads - five that print "Hello", and five that count down. So the most likely outcome is that your program will try to print "Hello" five times at the same time, and also count down five times at the same time.
If you want to do things in a particular order, don't do them all in separate threads. Just have one thread that does the things in the right order.

Tracking where a user has landed in a board game

The idea of the program is that it simulates a game board with a user-inputted number of sides, and cells per side. The program then needs to simulate the user rolling two six-sided dice continuously until the starting tile is landed on or passed.
The problem I'm having is with a required function that records the spot the user landed on the most, per side of the game board (like a Monopoly board has 4 sides). For example, a Monopoly board with 4 sides, 10 cells on each side.
Side 1 has Cells 1 - 10
Side 2 has Cells 11 - 20
Side 3 has Cells 21 - 30
Side 4 has Cells 31 - 40
I'd need to report which cells I landed on the most for each of those four sides, or however many sides the gameboard has.
I have no idea how to start this function. I don't want the code to be written out for me, just a nudge in the right direction. As for the rest of the program, this is what I have:
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
using namespace std;
int rollNDice(int nDice, int nSides) {
int diceSum = 0;
for (int i = 0; i < nDice; i++) {
int randnum = 1 + (rand() % (nSides - 1 + 1));
diceSum = diceSum + randnum;
}
return diceSum;
}
int mostLandings(const int boardVector, int startInterval, int endInterval) {
}
int main() {
srand(333);
int boardSides = 0;
int boardSpotsPerSide = 0;
int numberOfSims = 0;
int diceMove = 0;
int startInterval = 0;
int endInterval = 0;
const int boardVector = 0;
cout << "How many sides of the board are there? ";
cin >> boardSides;
cout << "How many spots on each side? ";
cin >> boardSpotsPerSide;
cout << "How many simulations? ";
cin >> numberOfSims;
for (int i = 0; i < boardSides;) {
const int boardVector = boardSides * boardSpotsPerSide;
int spotsPerInterval = boardVector / boardSides;
startInterval = spotsPerInterval / spotsPerInterval + (10 * i);
endInterval = spotsPerInterval * (i + 1);
mostLandings(boardVector, startInterval, endInterval)
i++;
}
}
One possible approach would be to start by calculating the total amount of squares on the board. The amount of squares q can be given by
q = 2s + (s-1)(n-1) = sn + s- n + 1
where s is the amount of squares on each side and n is the amount of sides. Next, store each roll value and loop over the sum of the roll value and the player's previous position, and store those values in a separate array. Take each element in that array modulo q and store in a separate array. This array should be the index of each square landed on after each subsequent turn, which you can manipulate and read from as you like.

Unexpected Output While Using Threads

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();
}