Situation:
A Factory
class member function manager
spawns two worker
threads. Each worker
thread run a loop for each day of an year, and increment their own var workHours
, and a shared var work
. At the end of each day, each worker
thread signals manager
to get their report of work
and workHours
When the manager
gets workHours
from both the worker
threads, it reports totalWorkHours
as (workHours[0] + workHours[1]
) to the boss
Problem:
Threads are not working as expected. Threads are running in multiple loops before reporting to the manager. They are not synced for each day reporting. How to achieve this thread syncing, that after each day, both threads report their stats to manager.
Code:
[The below code is has no compile errors, in case you want to test run, edit]
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
using namespace std;
class Factory{
public:
Factory() {
work = 0;
workHours[0] = 0;
workHours[1] = 0;
};
void manager();
private:
std::thread threads[2];
std::mutex m_lock;
std::condition_variable cond[2];
int work; // Shared across threads
int workHours[2]; // One var for each thread
int totalWorkHours;
void worker(int id);
void boss(int work, int workHours);
};
void Factory::worker(int id)
{
cout<< id <<" Started Working "<<endl;
for (int day = 0; day<365; day++)
{
std::unique_lock<std::mutex> lck{ m_lock };
work++;
workHours[id]++;
cout << id << " working " << endl;
cond[id].notify_one();
lck.unlock();
std::this_thread::sleep_for(1s);
}
}
void Factory::manager()
{
int wHrs0, wHrs1;
threads[0] = std::thread([&](Factory *fac) { fac->worker(0); }, this);
threads[1] = std::thread([&](Factory *fac) { fac->worker(1); }, this);
//for (int day=0; day<365; day++)
for (;;)
{
std::unique_lock<mutex> lck0{ m_lock };
cond[0].wait(lck0);
cout << "Worker0 workHours : " << workHours[0] << " Total Work : " << work << endl;
wHrs0 = workHours[0];
lck0.unlock();
std::unique_lock<mutex> lck1{ m_lock };
cond[1].wait(lck1);
cout << "Worker1 workHours : " << workHours[1] << " Total Work : " << work << endl;
wHrs1 = workHours[1];
lck1.unlock();
totalWorkHours = wHrs0 + wHrs1;
cout << "Both Workers Worked one day" << endl;
boss(work, totalWorkHours);
}
}
void Factory::boss(int work, int workHours)
{
cout << "I am not Happy with just " << work << " amount of work in damn " << workHours << " Hrs " << endl;
}
int main()
{
Factory nike;
nike.manager();
//wait for keypress
cin.get();
return 0;
}
I solved it myself. Posting here for reference.
worker
waits for manager
to consume the work result. And manager
waits for both worker
s to finish one day work.
// Example program
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
class Factory{
public:
Factory() {
work = 0;
workHours[0] = 0;
workHours[1] = 0;
};
void manager();
private:
std::thread threads[2];
std::mutex m_lock;
std::condition_variable cond[2];
std::condition_variable condMan;
bool resFetch[2];
bool resAvailable[2];
int work; // Shared across threads
int workHours[2]; // One var for each thread
int totalWorkHours;
void worker(int id);
void boss(int work, int workHours);
};
void Factory::worker(int id)
{
cout<< id <<" Started Working "<<endl;
for (int day = 0; day<365; day++)
{
std::unique_lock<std::mutex> lck{ m_lock };
while(!resFetch[id])
condMan.wait(lck);
resFetch[id] = false;
work++;
workHours[id]++;
cout << id << " working " << endl;
resAvailable[id] = true;
cond[id].notify_one();
lck.unlock();
std::this_thread::sleep_for(1s);
}
}
void Factory::manager()
{
int wHrs0, wHrs1;
threads[0] = std::thread([&](Factory *fac) { fac->worker(0); }, this);
threads[1] = std::thread([&](Factory *fac) { fac->worker(1); }, this);
for (;;)
{
std::unique_lock<std::mutex> lck{ m_lock };
resFetch[0] = true;
resFetch[1] = true;
condMan.notify_all();
while(!resAvailable[0])
cond[0].wait(lck);
cout << "Worker0 workHours : " << workHours[0] << " Total Work : " << work << endl;
wHrs0 = workHours[0];
resAvailable[0] = false;
while (!resAvailable[1])
cond[1].wait(lck);
cout << "Worker1 workHours : " << workHours[1] << " Total Work : " << work << endl;
wHrs1 = workHours[1];
resAvailable[1] = false;
lck.unlock();
totalWorkHours = wHrs0 + wHrs1;
cout << "Both Workers Worked one day" << endl;
boss(work, totalWorkHours);
}
}
void Factory::boss(int work, int workHours)
{
cout << "I am not Happy with just " << work << " amount of work in damn " << workHours << " Hrs " << endl;
}
int main()
{
Factory nike;
nike.manager();
//wait for keypress
cin.get();
return 0;
}