#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <semaphore.h>
using namespace std;

//compile method: g++ thread.cpp -pthread

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
sem_t empty;
sem_t full;
const int size=1000;
int Buffer[size] = {0};
int top = -1;
int iNum = 0;


void printids(const char *s)
{
    pthread_t   tid;
 
    tid = pthread_self();
    printf("%s tid %lu (0x%lx)\n", s, (unsigned long)tid, (unsigned long)tid);
}

bool IsFull()
{
	
}

void *producer(void *arg)
{
	printids("new thread: ");
	
	while(1)
	{
		while(1)
		{
			if(top<size-1)
				break;	
		}
		
 		sem_wait( &empty ); // producer: empty-1
 		pthread_mutex_lock( &mutex1 );
		
		usleep(10);
		
 		Buffer[++top] = ++iNum;
 		printf("\nP[%d]=%d",top,iNum);
 		
 		pthread_mutex_unlock( &mutex1 );
 		sem_post( &full ); //producer: full+1
		
		if(iNum==10000)
			pthread_exit(NULL);
	}
	
    return((void *)0);
}

void *consumer(void *arg)
{
	printids("new thread: ");
	
	while(1)
	{
		while(1)
		{
			if(top>=0)
				break;	
		}
		
		//usleep(10000);
		
 		sem_wait( &full ); //comsumer: full-1
 		pthread_mutex_lock( &mutex1 );
			
 		Buffer[top] = 0;
 		printf("\nC[%d]=%d",top,iNum);
 		--top;		
		
 		pthread_mutex_unlock( &mutex1 );
 		sem_post( &empty ); //comsumer: empty+1

		if(iNum==10000)
			pthread_exit(NULL);
	}
	
    return((void *)0);
}
 
int main(void)
{
	int err;
	pthread_t thread1;
	pthread_t thread2;
	
	sem_init(&empty, 0, 1000);
	sem_init(&full, 0, 0);
	
	err = pthread_create(&thread1, NULL, producer, (char *)"A");
	if(err != 0)
	{
		printf("\n can't create thread");
	}
	err = pthread_create(&thread2, NULL, consumer, (char *)"B");
	if(err != 0)
	{
		printf("\n can't create thread");
	}
	
	printids("main thread:");
	
	pthread_join( thread1, NULL);
	pthread_join( thread2, NULL);
	
	printids("\n end.");
	
	exit(0);
}