Skip to content

Instantly share code, notes, and snippets.

@lazy
Created April 3, 2020 09:31
Show Gist options
  • Save lazy/2f0d61e97718149f5060d1a5f2e01e9d to your computer and use it in GitHub Desktop.
Save lazy/2f0d61e97718149f5060d1a5f2e01e9d to your computer and use it in GitHub Desktop.
class FizzBuzz {
private:
int n;
int next;
mutex m;
map<int, condition_variable*> waiters;
public:
FizzBuzz(int n) {
this->n = n;
this->next = 1;
}
// printFizz() outputs "fizz".
void fizz(function<void()> printFizz) {
run(3, [](int val) { return val % 5 != 0; }, [&](int) { printFizz(); });
}
// printBuzz() outputs "buzz".
void buzz(function<void()> printBuzz) {
run(5, [](int val) { return val % 3 != 0; }, [&](int) { printBuzz(); });
}
// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(function<void()> printFizzBuzz) {
run(15, [](int val) { return true; }, [&](int) { printFizzBuzz(); });
}
// printNumber(x) outputs "x", where x is an integer.
void number(function<void(int)> printNumber) {
run(1, [](int val) { return val % 3 != 0 && val % 5 != 0; }, printNumber);
}
private:
void run(int step, function<bool(int)> cond, function<void(int)> print)
{
condition_variable cv;
for (auto i = step; i <= n; i += step)
{
if (cond(i))
{
unique_lock lk(m);
if (this->next != i)
{
this->waiters[i] = &cv;
cv.wait(lk, [&]() { return this->next == i; });
}
print(i);
++this->next;
auto it = this->waiters.find(this->next);
if (it != this->waiters.end())
{
auto waiter_cv = it->second;
this->waiters.erase(it);
waiter_cv->notify_one();
}
}
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment