Print Foo Bar Alternately
code (semaphore) wrong
class FooBar {
private:
int n;
std::binary_semaphore sem{0};
public:
FooBar(int n) {
this->n = n;
}
void foo(function<void()> printFoo) {
for (int i = 0; i < n; i++) {
// printFoo() outputs "foo". Do not change or remove this line.
printFoo();
sem.release();
}
}
void bar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
sem.acquire();
// printBar() outputs "bar". Do not change or remove this line.
printBar();
}
}
};
what is wrong?
- it failed to wake the other thread after the first print. so the first thread will print "foo" and then block on
sem.release()(because it is a binary semaphore), while the second thread will block onsem.acquire()and never get a chance to print "bar" (because count is 0). - we need to notify the other thread after each print, so that it can proceed to print the next part. We can use two semaphores to achieve this: one for "foo" and one for "bar".
code (semaphore) correct
class FooBar {
private:
int n;
std::binary_semaphore fo{0};
std::binary_semaphore ba{1}; //very important to trigger the first print
public:
FooBar(int n) {
this->n = n;
}
void foo(function<void()> printFoo) {
for (int i = 0; i < n; i++) {
ba.acquire();
// printFoo() outputs "foo". Do not change or remove this line.
printFoo();
fo.release();
}
}
void bar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
fo.acquire();
// printBar() outputs "bar". Do not change or remove this line.
printBar();
ba.release();
}
}
};
questions
can we remove the for loop?
No, we cannot remove the for loop because we need to print "foo" and "bar" n times. The for loop ensures that the printing happens n times, and the semaphores ensure that the order of printing is maintained. If we remove the for loop, we would only print "foo" and "bar" once, which does not meet the requirements of the problem.