C/C++ | 3 ways to solve: atomic; mutex; semaphore
1st way in C++: atomic\nExplanation: \n\natomic variables atomic<T> have mutex locks embedded in them. \n\nThe idea is that, if a thread acquires the lock, no o
# 1st way in C++: atomic\nExplanation: \n\natomic variables `atomic<T>` have `mutex locks` embedded in them. \n\nThe idea is that, if a thread acquires the lock, no other thread can acquire it (ie. modify it) until it is released.\n\nWell just how to tell the program to lock/unlock? \nUse `this_thread::yield()`, which, after a job (printFoo or printBar) is done, will `reschedule` the same job of that thread, allowing other threads to run.\n```go\nclass FooBar {\nprivate:\n    int             n;\n    atomic<bool>    alt; // added\n\npublic:\n    FooBar(int n)\n    {\n        this->n = n;\n        alt = false;\n    }\n\n    void foo(function<void()> printFoo) {\n        \n        for (int i = 0; i < n; i++)\n        {\n\t\t/* solution part start */\n\t\twhile (alt)\n\t\t{\n\t\t\tthis_thread::yield();\n\t\t}\n\t\t/* end */\n\n\t\t// printFoo() outputs "foo". Do not change or remove this line.\n\t\tprintFoo();\n\n\t\talt = !alt; // added\n        }\n    }\n\n    void bar(function<void()> printBar) {\n        \n        for (int i = 0; i < n; i++)\n        {\n\t\t/* solution part start */\n\t\twhile (!alt)\n\t\t{\n\t\t\tthis_thread::yield();\n\t\t}\n\t\t/* end */\n\n\t\t// printBar() outputs "bar". Do not change or remove this line.\n\t\tprintBar();\n\n\t\talt = !alt; // added\n        }\n    }\n};\n```\n\n\n\n# 1st way in C: atomic\nExplanation: \n\nIn C, the same task is implemented using <kbd> signal </kbd>\n`sig_atomic_t  alt` is equivalent to `atomic<bool>  alt` in C++.\n\nOne perk to notice is that `sig_atomic_t` is actually of <kbd> int type </kbd>.\nIt means that even if we use an `int  alt;`, the solution will also be accepted XD\n\nThen `sched_yield();` is equivalent to `this__thread::yied();` in C++.\n\n```go\n#include <signal.h>\n\ntypedef struct\n{\n    int             n;\n    sig_atomic_t    alt; // added\n}   FooBar;\n\nFooBar* fooBarCreate(int n)\n{\n    FooBar* obj = (FooBar*) malloc(sizeof(FooBar));\n    obj->n = n;\n\n    obj->alt = 0; // added\n\n    return obj;\n}\n\nvoid foo(FooBar* obj)\n{    \n    for (int i = 0; i < obj->n; i++)\n    {\n        /* added part start */\n        while (obj->alt)\n        {\n            sched_yield();\n        }\n        /* end */\n\n        // printFoo() outputs "foo". Do not change or remove this line.\n        printFoo();\n\n        obj->alt = 1; // added\n    }\n}\n\nvoid bar(FooBar* obj)\n{    \n    for (int i = 0; i < obj->n; i++)\n    {\n        /* added part start */\n        while (!obj->alt)\n        {\n            sched_yield();\n        }\n        /* end */\n\n        // printBar() outputs "bar". Do not change or remove this line.\n        printBar();\n\n        obj->alt = 0; // added\n    }\n}\n\nvoid fooBarFree(FooBar* obj)\n{\n    if (obj)\n        free(obj);\n}\n```\n\n# 2nd way in C++: mutex\n\nThe most intuitive and simplest way is to use 2 `mutex`.\nOne for each function, ie. one mutex for `foo()` and the other for `bar()`.\n\nTo start, the "bar()" mutex is locked first. \nThen we alternatively lock and unlock both mutex:\n\n```go\nclass FooBar {\nprivate:\n    int             n;\n    mutex           food; // added\n    mutex           bart; // added\n\npublic:\n    FooBar(int n)\n    {\n        this->n = n;\n        bart.lock(); // added\n    }\n\n    void foo(function<void()> printFoo) {\n        \n        for (int i = 0; i < n; i++)\n        {\n            food.lock(); // added\n\n            // printFoo() outputs "foo". Do not change or remove this line.\n        \tprintFoo();\n\n            bart.unlock(); // added\n        }\n    }\n\n    void bar(function<void()> printBar) {\n        \n        for (int i = 0; i < n; i++)\n        {\n            bart.lock(); // added\n            // printBar() outputs "bar". Do not change or remove this line.\n        \tprintBar();\n\n            food.unlock(); // added\n        }\n    }\n};\n```\n\n# 2nd way in C: mutex\n\nExplanation: \n\nSame things as in C++ mutex locking, just that some <kdb>writing</kbd> is different:\n\nTo declare mutex, use `pthread_mutex_t  mtx`.\nWe also have to init them first `pthread_mutex_init(& mtx, NULL);`\nThen in each thread we do the same sequence, locking/unlocking each mutex:\n```cpp\npthread_mutex_lock(& mtx1);\nprint();\npthread_mutex_unlock(& mtx2)\n```\nThe entire code:\n```go\n# include "pthread.h"\n\ntypedef struct \n{\n    pthread_mutex_t     mtx_foo; // +\n    pthread_mutex_t     mtx_bar; // +\n    int                 n;\n    \n}   FooBar;\n\nFooBar* fooBarCreate(int n)\n{\n    FooBar* obj = (FooBar*) malloc(sizeof(FooBar));\n    obj->n = n;\n\n    pthread_mutex_init(& obj->mtx_foo, NULL); // +\n    pthread_mutex_init(& obj->mtx_bar, NULL); // +\n\n    return obj;\n}\n\nvoid foo(FooBar* obj)\n{\n    for (int i = 0; i < obj->n; i++)\n    {\n        pthread_mutex_lock(& obj->mtx_bar); // +\n        // printFoo() outputs "foo". Do not change or remove this line.\n        printFoo();\n        pthread_mutex_unlock(& obj->mtx_foo); // +\n    }\n}\n\nvoid bar(FooBar* obj) {\n    \n    for (int i = 0; i < obj->n; i++)\n    {\n        pthread_mutex_lock(& obj->mtx_foo); // +\n        // printBar() outputs "bar". Do not change or remove this line.\n        printBar();\n        pthread_mutex_unlock(& obj->mtx_bar); // +\n    }\n}\n\nvoid fooBarFree(FooBar* obj)\n{\n    if (obj)\n        free(obj);\n}\n```\n\n# 3rd way in C++: semaphore\n\nIn this leetcode problem, using `semaphore` is similar to mutex in C. \n\n`sem_init` is equivalent to `pthread_mutex_init`\nThe second parameter is set to 0, as we have only one process (1 for management between processes; 0 for between threads of a single process). \n\nThe thrid parameter sets the initial value/order for a semaphore. In this case it is set to 0 and 1 respectively. \n\nThen we use `sem_wait` & `sem_wait` in place of mutex_lock and mutex_unlock.\n\n```go\n#include "semaphore.h" /* added */\n\nclass FooBar {\nprivate:\n    int         n;\n    sem_t       food;\n    sem_t       bart;\n\npublic:\n    FooBar(int n)\n    {\n        this->n = n;\n        sem_init(& food, 0, 0); /* added: */\n        sem_init(& bart, 0, 1); /* added: */\n    }\n\n    void foo(function<void()> printFoo)\n    {\n        \n        for (int i = 0; i < n; i++)\n        {\n            sem_wait(& bart); /* added */\n\n            // printFoo() outputs "foo". Do not change or remove this line.\n\t\t\tprintFoo();\n\n            sem_post(& food); /* added */\n        }\n    }\n\n    void bar(function<void()> printBar)\n    {\n        \n        for (int i = 0; i < n; i++)\n        {\n            sem_wait(& food); /* added */\n\n\t\t\t// printBar() outputs "bar". Do not change or remove this line.\n\t\t\tprintBar();\n\n            sem_post(& bart); /* added */\n        }\n    }\n};\n```\n\n# 3rd way in C: semaphore\n```go\ntypedef struct \n{\n    int         n;\n\n    sem_t       foo_; // added\n    sem_t       bar_; // added\n    \n} FooBar;\n\nFooBar* fooBarCreate(int n) {\n    FooBar* obj = (FooBar*) malloc(sizeof(FooBar));\n    obj->n = n;\n\n    sem_init(& obj->foo_, 0, 0); // added\n    sem_init(& obj->bar_, 0, 1); // added\n\n    return obj;\n}\n\nvoid foo(FooBar* obj) {\n    \n    for (int i = 0; i < obj->n; i++)\n    {\n        sem_wait(& obj->bar_); // added\n\n        // printFoo() outputs "foo". Do not change or remove this line.\n        printFoo();\n\n        sem_post(& obj->foo_); // added\n    }\n}\n\nvoid bar(FooBar* obj) {\n    \n    for (int i = 0; i < obj->n; i++)\n    {\n        sem_wait(& obj->foo_); // added\n\n        // printBar() outputs "bar". Do not change or remove this line.\n        printBar();\n\n        sem_post(& obj->bar_); // added\n    }\n}\n\nvoid fooBarFree(FooBar* obj)\n{\n    sem_destroy(& obj->foo_); // added\n    sem_destroy(& obj->bar_); // added\n}\n```
['C', 'C++']