#include <pthread.h>
//#include<semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

pthread_mutex_t x,wsem;
int readcount;
int data;

void intialize()
{
    pthread_mutex_init(&x,NULL);
    pthread_mutex_init(&wsem,NULL);
    readcount=0;
    data=0;
}

void * reader (void * param)
{
    int waittime;

    //printf("\nReader id= %lu is trying to enter",pthread_self());
    pthread_mutex_lock(&x);
    readcount++;
    if(readcount==1){
        pthread_mutex_lock(&wsem);}
    printf("\nReader id= %lu has entered",pthread_self());
    printf("\n%d Reader is inside ",readcount);
    pthread_mutex_unlock(&x);
    waittime = ((rand()%5+1))*1000;
    printf("\n Reader sleep: %d s ",(waittime/1000));
    printf("\n Reader data: %d ",data);
    Sleep(waittime);
    printf("\nReader id= %lu is Leaving",pthread_self());
    pthread_mutex_lock(&x);
    readcount--;
    if(readcount==0){
        //printf("\nReader id= %lu is Leaving",pthread_self());
        pthread_mutex_unlock(&wsem);
        //printf("\nReader id= %lu is Leaving",pthread_self());
    }
    //printf("\nReader id= %lu is Leaving",pthread_self());
    pthread_mutex_unlock(&x);
    //printf("\nReader id= %lu is Leaving",pthread_self());
    pthread_exit(NULL);
}

void * writer (void * param)
{
    int waittime;

    //printf("\nWriter id= %lu is trying to enter",pthread_self());
    pthread_mutex_lock(&wsem);
    printf("\nWrite id= %lu has entered",pthread_self());
    waittime=((rand()%3)+1)*1000;
    printf("\n Writer sleep: %d s ",(waittime/1000));
    data = rand()%50;
    printf("\n Writer update data: %d ",data);
    Sleep(waittime);
    printf("\nWriter id= %lu is leaving",pthread_self());
    pthread_mutex_unlock(&wsem);
    //printf("\nWriter id= %lu is leaving",pthread_self());
    //Sleep(30);
    pthread_exit(NULL);
    //exit(0);
}

int main()
{
    int n1,n2,i;
    printf("\nEnter the no of writers: ");
    scanf("%d",&n1);
    printf("\nEnter the no of readers: ");
    scanf("%d",&n2);
    intialize();
    pthread_t writerThreads[n1],readThreads[n2];
    for(i=0;i<n1;i++){
        pthread_create(&writerThreads[i],NULL,writer,NULL);}
    for(i=0;i<n2;i++){
        pthread_create(&readThreads[i],NULL,reader,NULL);}
    for(i=0;i<n1;i++){
        pthread_join(writerThreads[i],NULL);}
    for(i=0;i<n2;i++){
        pthread_join(readThreads[i],NULL);}
    //Sleep(30);
    exit(0);
}