Sample that uses condition variables.
Conditional variables generally use certain combinations of the following values.
Follow the steps below to wait to be notified from other threads.
Follow the steps below to notify other threads.
The even and odd threads signal each other to continue the process in this sample.
using ::nlib_ns::threading::ScopedLock;
using ::nlib_ns::threading::UniqueLock;
using ::nlib_ns::threading::CondVar;
using ::nlib_ns::threading::SimpleCriticalSection;
using ::nlib_ns::threading::Thread;
const int NUM_THREADS = 6;
Thread g_Th[NUM_THREADS];
struct CondVarState {
CondVar cond;
SimpleCriticalSection lock;
bool flag;
public:
CondVarState() : flag(false) {}
} g_Cond1, g_Cond2;
class ThreadParam {
public:
ThreadParam() : m_ThreadNum(0), m_Status(false), m_Wait(NULL), m_Signal(NULL) {}
void Initialize(int num, CondVarState* w, CondVarState* s) {
m_ThreadNum = num;
m_Wait = w;
m_Signal = s;
m_Status = true;
}
void Exec();
static void ThreadFunc(ThreadParam* param) { param->Exec(); }
bool IsSuccessful() { return m_Status; }
private:
int m_ThreadNum;
bool m_Status;
CondVarState* m_Wait;
CondVarState* m_Signal;
};
void ThreadParam::Exec() {
{
UniqueLock<SimpleCriticalSection> lock(m_Wait->lock);
while (!m_Wait->flag) {
errno_t e = m_Wait->cond.Wait(lock);
if (e != 0) {
m_Status = false;
return;
}
nlib_printf(
" Thread %d may be notified and acquires lock\n", m_ThreadNum);
}
nlib_printf(
" Thread %d is notified, and do its own job\n", m_ThreadNum);
m_Wait->flag = false;
}
{
ScopedLock<SimpleCriticalSection> lock(m_Signal->lock);
m_Signal->flag = true;
m_Signal->cond.NotifyAll();
}
}
bool CondVarDemo() {
ThreadParam param[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
if (i % 2 == 0) {
param[i].Initialize(i, &g_Cond1, &g_Cond2);
e = g_Th[i].Start(ThreadParam::ThreadFunc, ¶m[i]);
} else {
param[i].Initialize(i, &g_Cond2, &g_Cond1);
e = g_Th[i].Start(ThreadParam::ThreadFunc, ¶m[i]);
}
if (e != 0) return false;
}
g_Cond1.lock.lock();
g_Cond1.flag = true;
g_Cond1.cond.NotifyAll();
g_Cond1.lock.unlock();
for (int i = 0; i < NUM_THREADS; ++i) {
e = g_Th[i].Join();
if (e != 0) return false;
}
for (int i = 0; i < NUM_THREADS; ++i) {
if (!param[i].IsSuccessful()) return false;
}
return true;
}
static bool SampleMain(int, char**) { return CondVarDemo(); }
NLIB_MAINFUNC