I found this code online explaining how to use a std::condition_variable
to solve the Producer-Consumer Problem: Producer-Consumer Problem Using Condition Variable in C++
#include <condition_variable> // std::condition_variale
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
std::mutex g_mutex;
std::condition_variable g_cv;
bool g_ready = false;
int g_data = 0;
int produceData() {
int randomNumber = rand() % 1000;
std::cout << "produce data: " << randomNumber << "\n";
return randomNumber;
}
void consumeData(int data) { std::cout << "receive data: " << data << "\n"; }
void consumer() {
int data = 0;
while (true) {
std::unique_lock<std::mutex> ul(g_mutex);
g_cv.wait(ul, []() { return g_ready; });
consumeData(g_data);
g_ready = false;
ul.unlock();
g_cv.notify_one();
}
}
void producer() {
while (true) {
std::unique_lock<std::mutex> ul(g_mutex);
g_data = produceData();
g_ready = true;
ul.unlock();
g_cv.notify_one();
ul.lock();
g_cv.wait(ul, []() { return g_ready == false; });
}
}
void consumerThread(int n) { consumer(); }
void producerThread(int n) { producer(); }
int main() {
int times = 100;
std::thread t1(consumerThread, times);
std::thread t2(producerThread, times);
t1.join();
t2.join();
return 0;
}
My code works, but my coding standard says I'm not allowed to use lambdas.
How can I use this code without using lambdas in wait()
?
I've tried the following, but it didn't work:
bool
wait(g_ready)
As commenters have pointed out, disallowing lambdas is a dubious decision for a coding standard. Regardless, lambdas are just convenience syntax for creating types with a call operator, which you could do by hand.
The lambda expression:
[]() { return g_ready; }
roughly translates into
struct g_ready_checker {
bool operator()() const noexcept {
return g_ready;
}
};
You could then do the following:
g_cv.wait(ul, g_ready_checker{});
We can also turn g_ready_checker
into a class template with a <bool DesiredValue>
parameter, or we could store the value g_ready
is meant to have as a class member.
Or alternatively, since this lambda isn't capturing anything, you could also write a free function, possibly as a template:
template <bool DesiredValue>
bool is_g_ready() {
return g_ready == DesiredValue;
}
/* ... */
g_cv.wait(ul, &is_g_ready<true>);
/* ... */
g_cv.wait(ul, &is_g_ready<false>);
Here, we provide wait
with a predicate which is a function pointer. Note that the Predicate
template parameter of std::condition_variable_wait
is not restricted to lambdas, it accepts anything callable which returns something convertible bool
.