C++ concurrent functions? - c++

I'm trying to stop randomFunction() when i == 5 in the main function. I do know that the current code for randomFunction() will only stop if counter equals 1000 and counter++ gets run 1000 times.
class A{
counter = 0;
public:
void randomFunction()
{
while(counter != 1000)
{
counter++;
cout << counter << endl;
}
cout << "Task Complete!" << endl;
}
void stopFunction()
{
counter = 1000;
}
};
int main()
{
A o;
o.randomFunction();
for (int i = 0; i < 6; i++)
{
if (i == 5)
{
o.stopFunction();
}
}
return 0;
}
Is there a way to run stopFunction() while randomFunction is running?
I'm looking for:
1
2
3
4
5
Task Complete!
And not:
1
...
1000
Task Complete!
I'm thinking the solution has to do with library thread and future or mutex, but I do not know where to start.

Related

Why am I not able to push a pair after a limit in the vector?

The problem is to find if a given sequence of numbers can form a valid permutation or not. The problem statement is trivial for the real problem. So, I am pushing a pair of integers into the vector. The first part being the number itself and second being 0 or 1.
The code works fine till a sequence 1041 long (specific after debugging a lot). Just to debug I added a print statement after pushing each pair inside the vector. For a length of 1042, the code shows pushed 1040 and then pushed 1 (which is weird) and then just hangs on there.
I am attaching the code as well as the input and terminal output.
You can just check the main function
Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;
bool comparator_function(pair<int, int> a, pair<int, int> b) {
return (a.first < b.first);
}
//index_added -> the index at which the latest element was added
void set_r_array(int* r_array_ref, int* per_array_ref, int size, int* count, int index_added) {
for(int i = 1;i <= size; i++) {
count[i] = 0;
}
int temp = index_added;
while(index_added <= size) {
if(index_added == size) {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = size;
break;
}
else {
r_array_ref[temp] = -1;
break;
}
}
else {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = index_added;
break;
}
else {
index_added++;
}
}
}
for(int i = 1;i <= size; i++) {
if(r_array_ref[i] != -1) {
count[r_array_ref[i]]++;
}
}
}
bool check_max(int* count, int next_element, int size) {
int max_count = -1, index = 0;
for(int i = 1;i <= size; i++) {
int temp_val = count[i];
if(max_count <= temp_val) {
max_count = temp_val;
index = i;
}
}
int num = 0;
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
num++;
}
}
//one max
if(num == 1) {
if(next_element == index) {
return true;
}
return false;
}
else {
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
if(next_element == i) {
return true;
}
}
}
return false;
}
}
int main() {
int testCases;
cin >> testCases;
cin.ignore();
while(testCases-- > 0) {
int n, result_flag = 0;
cin >> n;
cin.ignore();
vector<pair<int, int>> per;
int temp;
for(int i = 0;i < n; i++) {
cin >> temp;
pair<int, int> temp_pair = make_pair(temp, i+1);
per.push_back(temp_pair);
//debug statement
cout << "pushed " << temp << endl;
}
auto start = std::chrono::high_resolution_clock::now();
cout << "start" << endl;
sort(per.begin(), per.end(), comparator_function);
int permutation_array[n+1], r_array[n+1], count[n+1];
for(int i = 0;i <= n; i++) {
permutation_array[i] = 0;
r_array[i] = i;
count[i] = 1;
}
cout << "end" << endl;
permutation_array[per[0].second] = per[0].first;
set_r_array(r_array, permutation_array, n, count, per[0].second);
//insertion of numbers
for(int i = 1;i < n; i++) {
//check if the next element inserted has the largest count rn or not
int next_element = per[i].second;
if(!check_max(count, next_element, n)) {
cout << "No" << endl;
result_flag = -1;
break;
}
permutation_array[per[i].second] = per[i].first;
set_r_array(r_array, permutation_array, n, count, per[i].second);
}
if(result_flag == 0) {
cout << "Yes" << endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
cout << "Time: " << duration.count() << " microseconds" << endl;
}
}
Input 1
1
5
2 3 4 5 1
Output 1
pushed 2
pushed 3
pushed 4
pushed 5
pushed 1
start
end
Yes
Input 2
1
1042
1 2 3 4 ... so on till 1042
Output 2
pushed 1
pushed 2
.
.
.
pushed 1040
pushed 1
and then hangs, from here on
The complexity of the code is O(n^2). So, I don't think it has to do anything with that. Since the input can be at max 10^4 order. Moreover, according to the print debugging, I think the issue is with the input.
You have issue with input as you reach console line limit.
Put your input into a file should solve that issue.
Then you should be able to debug your algorithm which seems more complicated than needed.

Multithreading Reuse with Objects in While loop

I'm new to multithreading and already started experiencing problems.
I would like to implement a 10 threads reuse on a Class' Function, whose Parent Class has 4 functions inside a while loop, but it gives me errors like "error C3867: 'std::thread::join': non-standard syntax; use '&' to create a pointer to member" and "std::system_error at memory location"
Since I don't know how well I explained it, I will show you pseudocode of what I would like to implement:
Main.cpp
Game newGame;
/* Create Players */
Population pop(NumberOfPlayers);
/* Create Enemies */
std::vector<Enemies> enemy;
for (int i = 0; i < NumberOfEnemies; i++) {
Enemies e(i);
enemy.push_back(e);
}
while (!pop.hasFinished) {
std::thread threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
threads[i] = std::thread(std::bind(&Population::populationMove, &pop, (i * NumberOfPlayers / NUM_THREADS)));
//std::cerr << "In Thread " << i << "\n";
}
for (int i = 0; i < NUM_THREADS; i++) {
if(threads[i].joinable)
threads[i].join;
//std::cerr << "In Thread " << i << "\n";
}
for (int i = 0; i < NumberOfEnemies; i++) {
enemy[i].movement();
enemy[i].checkIfKills();
}
enemymoves++;
if (pop.checkIfAllDead()) {
pop.calculateBest();
pop.createNewPopulation();
for (int i = 0; i < NumberOfEnemies; i++) {
if ((pop.gen - 1) % 5 == 0) {
enemy[i].save();
}
enemy[i].reset();
}
}
}
This is the pseudocode for populationMove()
Population::populationMove(int threadStartIndex) {
for (int i = threadStartIndex; i < threadStartIndex + (player.size() / NUM_THREADS); i++) {
mtx.lock();
player[i].move();
mtx.unlock();
}
Okay, I think this is your first problem.
std::thread threads[N_THREADS]; // array of threads
This will construct 10 threads, not SPACE for 10 threads. I wasn't absolutely positive, so I tested this way:
#include <iostream>
using namespace std;
class Foo {
public:
Foo() { cout << "Foo constructor.\n"; }
};
int main(int, char **) {
cout << "Allocate array.\n";
Foo array[10];
cout << "Loop.\n";
for (int i = 0; i < 10; ++i) {
array[i] = Foo();
}
cout << "Done.\n";
}
This displayed the output from my first prompt, then 10 "Foo constructor" messages, then my second "Loop" prompt, then 10 more "Foo constructor" messages.
I think you probably need to make that an array of thread pointers, and then use new, like this:
std::thread * thread[N_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
threads[i] = new std::thread(std::bind(&Population::populationMove, &pop, (i * NumberOfPlayers / NUM_THREADS)));
}
Next, thread.join is a method:
for (int i = 0; i < NUM_THREADS; i++) {
if(threads[i].joinable())
threads[i].join();
//std::cerr << "In Thread " << i << "\n";
}
You are missing () in two places in that code.

Fixing a race condition C++

I'm working on building a rate monotonic scheduler for an assignment. I'm running into a racing condition with my overrun counter. The overrun counter is supposed to say 0 for all 4 threads yet I'm constantly getting very strange numbers. I would really appreciate some help in both identifying where the race condition is occurring and how to fix it. Thanks in advance.
NOTE: If it matters I'm using Cygwin for Windows to compile this program
My Scheduler.cpp file:
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <mutex>
#include <condition_variable>
#include <semaphore.h>
using namespace std;
sem_t mutex1;
sem_t mutex2;
sem_t mutex3;
sem_t mutex4;
// initialze variables
int i = 0;
int overrun1 = 0;
int overrun2 = 0;
int overrun3 = 0;
int overrun4 = 0;
int loop1 = 0;
int loop2 = 0;
int loop3 = 0;
int loop4 = 0;
bool thread1FinishFlag = false;
bool thread2FinishFlag = false;
bool thread3FinishFlag = false;
bool thread4FinishFlag = false;
pthread_attr_t mattr;
pthread_attr_t tattr;
int mainpriority = 1;
int threadpriority = 2;
int doWork();
void nsleep();
void* p1(void *param);
void* p2(void *param);
void* p3(void *param);
void* p4(void *param);
int main(int argc, char const *argv[])
{
sem_init(&mutex1, 0, 0);
sem_init(&mutex2, 0, 0);
sem_init(&mutex3, 0, 0);
sem_init(&mutex4, 0, 0);
// initialze all threads
pthread_t thread1;
pthread_t thread2;
pthread_t thread3;
pthread_t thread4;
// actually create all threads
pthread_create(&thread1, NULL, p1, NULL);
pthread_create(&thread2, NULL, p2, NULL);
pthread_create(&thread3, NULL, p3, NULL);
pthread_create(&thread4, NULL, p4, NULL);
while (i < 160)
{
//a possible start for the race condition
nsleep();
if (i == 0) // initial case. at time 0 schedule all threads
{
sem_post(&mutex1);
sem_post(&mutex2);
sem_post(&mutex3);
sem_post(&mutex4);
}
else if (i % 16 == 0) // last case which happens every 16 units which schedules all threads again
{
if (thread1FinishFlag == false){overrun1++;}
if (thread2FinishFlag == false){overrun2++;}
if (thread3FinishFlag == false){overrun3++;}
if (thread4FinishFlag == false){overrun4++;}
sem_post(&mutex1);
sem_post(&mutex2);
sem_post(&mutex3);
sem_post(&mutex4);
}
else if (i % 4 == 0) // case that happens every 4 units of time
{
if (thread1FinishFlag == false){overrun1++;}
if (thread2FinishFlag == false){overrun2++;}
if (thread3FinishFlag == false){overrun3++;}
sem_post(&mutex1);
sem_post(&mutex2);
sem_post(&mutex3);
}
else if (i % 2 == 0) // case that happens every other unit of time
{
if (thread1FinishFlag == false){overrun1++;}
if (thread2FinishFlag == false){overrun2++;}
sem_post(&mutex1);
sem_post(&mutex2);
}
else if (i % 1 == 0) // case that happens every unit of time
{
if (thread1FinishFlag == false){overrun1++;}
sem_post(&mutex1);
}
i++; // increment i to go through the loop again
}
cout << "Total runs: " << i << endl;
cout << "Thread 1 overruns: " << overrun1 << endl;
cout << "Thread 2 overruns: " << overrun2 << endl;
cout << "Thread 3 overruns: " << overrun3 << endl;
cout << "Thread 4 overruns: " << overrun4 << endl;
cout << "Total thread1 runs: " << loop1 << endl;
cout << "Total thread2 runs: " << loop2 << endl;
cout << "Total thread3 runs: " << loop3 << endl;
cout << "Total thread4 runs: " << loop4 << endl;
sleep(1);
pthread_cancel(thread1);
pthread_cancel(thread2);
pthread_cancel(thread3);
pthread_cancel(thread4);
return 0;
}
// doWork function
int doWork()
{
int lousyArray[10][10];
int product = 1;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
lousyArray[i][j] = 1;
}
}
for (int k = 0; k < 1; k++)
{
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 10; i++)
{
product *= lousyArray[i][j];
}
}
}
return 1;
}
//I believe the race condition begins here but I could be wrong
void* p1(void *param)
{
thread1FinishFlag = false;
while(1)
{
sem_wait(&mutex1);
thread1FinishFlag = false;
for (int i = 0; i < 1; i++)
{
doWork();
}
loop1++;
thread1FinishFlag = true;
}
}
void* p2(void *param)
{
thread2FinishFlag = false;
while(1)
{
sem_wait(&mutex2);
thread2FinishFlag = false;
for (int i = 0; i < 2; i++)
{
doWork();
}
loop2++;
thread2FinishFlag = true;
}
}
void* p3(void *param)
{
thread3FinishFlag = false;
while(1)
{
sem_wait(&mutex3);
thread3FinishFlag = false;
for (int i = 0; i < 4; i++)
{
doWork();
}
loop3++;
thread3FinishFlag = true;
}
}
void* p4(void *param)
{
thread4FinishFlag = false;
while(1)
{
sem_wait(&mutex4);
thread4FinishFlag = false;
for (int i = 0; i < 16; i++)
{
doWork();
}
loop4++;
thread4FinishFlag = true;
}
}
void nsleep()
{
struct timespec delay;
delay.tv_sec = 0;
delay.tv_sec = 100000000L;
nanosleep(&delay, NULL);
}
The thread[x]FinishFlag variables are accessed and modified by multiple concurrent execution threads -- namely the main execution thread and one other execution thread, for each of these variables -- but without proper sequencing.
That's at least one obvious undefined behavior with the shown code, and is sufficient enough to result in your observed bug.
You must either use atomic variables, or introduce proper mutex locks, when accessing variables from multiple concurrent execution threads.
Implementing proper sequencing should also automatically solve a few other concurrency-related issues with the shown code.
It also wouldn't hurt to replace four copies of all variables with proper arrays/vectors. Replacing all the foo_1, foo_2, foo_3, and foo_4s with just one vector, and replacing four duplicate copies of the same thread function with a single, clean function, will result in much smaller code, and fewer opportunities to introduce more bugs.

Code for calculating jobs remaining for Chef

Recently while practicing in codechef I came across this problem.
Everything went fine , it was an easy problem , simple logic , well it took no more than 10 mins to cook the code and it also ran fine in my machine but giving a Runtime Error(SIGSEGV) when I try to execute it in codechef.
I thought there might some problem with the arrays I have used , no help, i tried to debug it with gdb it also shows well , i even tried big test cases like about 1000 or so , it ran fine , then why its showing a runtime error in codechef?
Here is the Code:
#include <iostream>
int main(){
int testCases;
std::cin >> testCases;
while(testCases--)
{
int jobs,n;
std::cin >> jobs >> n;
int doneJobs[n];
for(int i = 0; i < n; i++)
{
std::cin >> doneJobs[i];
}
bool todoJobs[jobs] = {false};
for(int i = 0; i < n; i++)
{
todoJobs[doneJobs[i] - 1] = true;
}
bool toSkip = false;
for(int i = 0; i < jobs; i++)
{
if(todoJobs[i] == false)
{
if(toSkip == false)
{
std::cout << i + 1 << ' ';
toSkip = true;
todoJobs[i] = true;
}
else
{
toSkip = false;
}
}
}
std::cout << std::endl;
for(int i = 0; i < jobs; i++)
{
if(todoJobs[i] == false)
{
std::cout << i+1 << ' ';
}
}
std::cout << std::endl;
}
return 0;
}
Edit :
Thanks to #DominiqueLorre for pointing out that some random values entered can result in an Runtime Error , but still I am getting it here is my edited code:
#include <iostream>
int main(){
int testCases;
std::cin >> testCases;
while(testCases--){
int jobs,n;
std::cin>>jobs>>n;
bool todoJobs[jobs] = {false};
for(int i=0;i<n;i++){
int testJob;
std::cin >> testJob;
todoJobs[testJob-1] = true;
}
bool toSkip = false;
for(int i=0;i<jobs;i++){
if(todoJobs[i] == false){
if(toSkip == false){
std::cout << i+1 << ' ';
toSkip = true;
todoJobs[i] = true;
}else{
toSkip = false;
}
}
}
std::cout << std::endl;
for(int i=0;i<jobs;i++){
if(todoJobs[i] == false){
std::cout << i+1 << ' ';
}
}
std::cout << std::endl;
}
return 0;
}
According to problem definition, it's stated that n,m satisfying 0 ≤ m ≤ n ≤ 1000 (in your code n => jobs, m => n), thus test case 0 0 is valid. However, the following snippet will causing runtime error if jobs is 0, since C++14 does not allow declaration of zero-sized dynamic array.
bool todoJobs[jobs] = {false};
Add statement to check the value of jobs before array allocation.
if (jobs <= 0) continue;

Exiting while loop after x number of loops

I have 2 layers of maps, the second of which points to a queue. I would like to extract a certain number of items from the queue (and hence the maps), but I seem to have problems inserting a break/return/exit (I'm not sure which to use in this case) in the right place.
This is the code:
#include <iostream>
#include <queue>
#include <map>
using namespace std;
int main()
{
typedef std::queue<int> MessageQueue;
typedef std::map<int, MessageQueue> PriorityMap;
typedef std::map<int, PriorityMap> ClientMap;
ClientMap clients;
int priorities = 7;
clients[10][1].push(1);
clients[10][1].push(2);
clients[10][5].push(3);
clients[10][7].push(3);
for (int j = 1; j<3; j++) //this determines how many times an element will be 'popped' from a queue
{
while (!clients[10].empty())
{
for (int i = priorities; i > 0; i--)
{
while (clients[10].find(i) != clients[10].end())
{
cout << "priority " << i << endl;
cout << clients[10][i].front() << endl;
clients[10][i].pop();
if (clients[10][i].empty())
clients[10].erase(i);
}
}
break; //I don't know where this should go in order for the while loop to stop executing after an element has been popped
}
}
return 0;
}
with this result
priority 7
3
priority 5
3
priority 1
1
priority 1
2
but the result I would like instead is
priority 7
3
priority 5
3
In the context of the main method, exit and return will basically do the same thing. Neither are recommended to do in the middle of a loop.
My recommendation:
bool done = false;
for (...; ... && !done; ...)
{
while (... && !done)
{
...
done = true;
...
}
}
Or, in the context of your problem:
int count = 2;
for (int j = 1; j<3 && count > 0; j++)
{
while (!clients[10].empty() && count > 0)
{
for (int i = priorities; i > 0 && count > 0; i--)
{
while (clients[10].find(i) != clients[10].end() && count > 0)
{
...
count--;
...
}
}
}
}
I know you can just do && count instead of && count > 0, but the latter is more readable.
Instead of the outer loop, use a counter and goto:
int countRemoved = 0;
while (!clients[10].empty())
{
for (int i = priorities; i > 0; i--)
{
while (clients[10].find(i) != clients[10].end())
{
cout << "priority " << i << endl;
cout << clients[10][i].front() << endl;
clients[10][i].pop();
if (clients[10][i].empty())
clients[10].erase(i);
if( ++countRemoved == 2 ) goto stop;
}
}
}
stop: