Threading Hair While on Pthreads

Due to multicore and hyperthreaded processors, threading is now a common task programmers need to perform whenever possible. Quite often we see ready template code online or even C++ library based implementations that makes it easy or us to cut & paste, make few changes and unleash on to market after several testings...

This is fairly common these days that hardly any programmer can escape due to higher productivity requiremets !

We we do threaded programming, it is sure to have concurrent processing. So we need some kind of synchronizations to make sure we don't corrupt some shared data. Now the question is how to come up with proper sync mechanism: mutex, spin-lock etc.,

Here is an example of such application of threading -

Q: Print a sequence like: 010203040506070809010011012013 .... using threaded routines. One can do it in one thread, but here we need to exercise threading.

 

It's necessary to see how minimal locking we can do. To do that it is good to look at the state diagram. For example if a thread just print zero, then it has to let other threads to print non-zero. 

Now one more requirement imposed is: Use three threads : One prints zeros, another one prints even numbers, yet another prints odd numbers.

 

Condition to analyze:: When can zero thread print ? -- It can print after any non-zero got print. When can an even number be printed:: - when zero thread is not allowed to print, and last non-zero thread was odd number thread.

Now here is an implementation. It is instructive, if you use paper pencil first...

//

//  main.c

//  OS

//

//  Created by Admin on 5/26/18.

//  Copyright © 2018 AdminProkash Sinha. All rights reserved.

//

 

#include <stdio.h>

#include "OS.h"

int main(int argc, const char * argv[]) {

    // insert code here...

 

    testOddEvenPrint();

 

    printf("\nHello, World!\n");

    return 0;

}

 

//

//  thd.c

//  OS

//

//  Created by Admin on 5/26/18.

//  Copyright © 2018 AdminProkash Sinha. All rights reserved.

//

 

 

#include <stdbool.h>

#include<stdio.h>

#include<string.h>

#include<pthread.h>

#include<stdlib.h>

#include<unistd.h>

 

/*

 * Create a multi threaded ( 3 thd ) that prints 0102030405060708....

 * Need mutual exclusion

 */

 

//pthread_mutex_t mutx;

_Bool IsZero = true;

_Bool IsOddNo = true;

 

void AC( pthread_mutex_t *L)

{

    // -- waitable may block

    pthread_mutex_lock(L);

    return;

}

 

void RL( pthread_mutex_t *L)

{

    pthread_mutex_unlock(L);

    return;

}

 

void printzero( void Lock)

{

    pthread_mutex_t* L = (pthread_mutex_t*)Lock;

    for (int i = 0; i < 20; i++){

        AC ( L );

        if ( IsZero ){

            printf("%d", 0);

            IsZero = false;

        }

        RL(L);

    }

 

    return NULL;

}

 

void printOdd( void Lock )

{

    static int OddNo = 1;

    pthread_mutex_t* L = (pthread_mutex_t*)Lock;

    for (int i = 0; i < 10; i++){

        AC ( L );

        if ( !IsZero && IsOddNo){

            printf("%d", OddNo);

            IsZero = true;

            IsOddNo = false;

            OddNo += 2;

        }

        RL(L);

    }

    return NULL;

}

 

void printEven( void Lock )

{

    static int EvenNo = 2;

    pthread_mutex_t* L = (pthread_mutex_t*)Lock;

    for (int i = 0; i < 10; i++){

        AC ( L );

        if ( !IsZero && !IsOddNo){

            printf("%d", EvenNo);

            IsZero = true;

            IsOddNo = true;

            EvenNo += 2;

        }

        RL(L);

    }

    return NULL;

}

 

void

testOddEvenPrint()

{

    int err;

    pthread_t tid0thd, tidOddthd, tidEventhd;

    pthread_mutex_t mutx;

 

    if (pthread_mutex_init(&mutx, NULL) != 0)

    {

        printf("\n mutex init failed\n");

        return ;

    }

    err = pthread_create(&tid0thd, NULL, &printzero, &mutx);

    if (err != 0){

        printf("\ncan't create thread printzero :[%s]", strerror(err));

        return ;

    }

    err = pthread_create(&tidOddthd, NULL, &printOdd, &mutx);

    if (err != 0){

        printf("\ncan't create thread printzero :[%s]", strerror(err));

        return ;

    }

    err = pthread_create(&tidEventhd, NULL, &printEven, &mutx);

    if (err != 0){

        printf("\ncan't create thread printzero :[%s]", strerror(err));

        return ;

    }

 

    pthread_join(tid0thd, NULL);

    pthread_join(tidOddthd, NULL);

    pthread_join(tidEventhd, NULL);

 

    pthread_mutex_destroy(&mutx);

    return;

}