C solution, 3 conditional variables
It\'s not the fastest but it is done in a right way. Threads are not checking all the time for their status, but wait for the wake up notificaion.\n\nNote, that
It\'s not the fastest but it is done in a right way. Threads are not checking all the time for their status, but wait for the wake up notificaion.\n\nNote, that this line is needed to guarantee that the thread will handle the event even if it has started waiting for the signal to wake up already after the signal was sent out:\n```\n        while(obj->s != ZERO) pthread_cond_wait(&obj->cz, &obj->m);\n```\nNormally, a thread should also check for a common "exit" flag to know when to exit. But in this case each thread counts to "n" and stops, so no need for that flag.\n```\ntypedef enum Status_s { ZERO, ODD, EVEN } Status;\n\ntypedef struct {\n    int n;\n    Status s;\n    pthread_mutex_t m;\n    pthread_condattr_t az;\n    pthread_condattr_t ae;\n    pthread_condattr_t ao;\n    pthread_cond_t cz;\n    pthread_cond_t ce;\n    pthread_cond_t co;\n} ZeroEvenOdd;\n\nZeroEvenOdd* zeroEvenOddCreate(int n) {\n    ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc(sizeof(ZeroEvenOdd));\n    obj->n = n;\n    obj->s = ZERO;\n    pthread_mutex_init(&obj->m, NULL);\n    pthread_cond_init(&obj->cz, &obj->az);\n    pthread_cond_init(&obj->ce, &obj->ae);\n    pthread_cond_init(&obj->co, &obj->ao);\n    return obj;\n}\n\nvoid zero(ZeroEvenOdd* obj) {\n    int i;\n    pthread_mutex_lock(&obj->m);\n    for(i=0;i<obj->n;i++)\n    {\n        while(obj->s != ZERO) pthread_cond_wait(&obj->cz, &obj->m);\n        printNumber(0);\n        obj->s = i%2 ? EVEN : ODD;\n        pthread_cond_signal(i%2 ? &obj->ce : &obj->co);\n    }\n    pthread_mutex_unlock(&obj->m);\n}\n\nvoid even(ZeroEvenOdd* obj) {\n    int i;\n    pthread_mutex_lock(&obj->m);\n    for(i=2;i<=obj->n;i+=2)\n    {\n        while(obj->s != EVEN) pthread_cond_wait(&obj->ce, &obj->m);\n        printNumber(i);\n        obj->s = ZERO;\n        pthread_cond_signal(&obj->cz);\n    }\n    pthread_mutex_unlock(&obj->m);\n}\n\nvoid odd(ZeroEvenOdd* obj) {\n    int i;\n    pthread_mutex_lock(&obj->m);\n    for(i=1;i<=obj->n;i+=2)\n    {\n        while(obj->s != ODD) pthread_cond_wait(&obj->co, &obj->m);\n        printNumber(i);\n        obj->s = ZERO;\n        pthread_cond_signal(&obj->cz);\n    }\n    pthread_mutex_unlock(&obj->m);\n}\n\nvoid zeroEvenOddFree(ZeroEvenOdd* obj) {\n    pthread_mutex_destroy(&obj->m);\n    pthread_cond_destroy(&obj->cz);\n    pthread_cond_destroy(&obj->ce);\n    pthread_cond_destroy(&obj->co);\n}\n```
['C']