#include <boost/thread.hpp>
#include <iostream>
#include <boost/lambda/lambda.hpp>

template<typename T, int size>
class CircularBuffer {
public:
	CircularBuffer();
	void put(const T& t);  // schrijf element  in de buffer. WACHT als buffer vol is!
	const T get();         // lees een element uit de buffer. WACHT als buffer leeg is!
	bool isEmpty();        // vraag of het buffer leeg is
private:
//	Nog invullen!
};


/* Implementeer hier de member functies van CircularBuffer! */

class TestCircularBuffer {
private:
	CircularBuffer<char, 10> b; // buffer dat getest wordt
	boost::mutex m_cout;        // zorgt voor mutual excusive gebruik van cout (1 thread tegelijk)
	void producer(char c);
	void consumer();
public:
	void run();
};

void TestCircularBuffer::producer(char c) { // memberfunctie voor producer thread
	{
	    boost::lock_guard<boost::mutex> lock(m_cout);
		std::cout<<"Thread: "<<boost::this_thread::get_id()<<" met arg: "<<c<< " gestart"<<std::endl;
	}
    for (int i(0); i<500; ++i) {
        b.put(c);
    }
	{
	    boost::lock_guard<boost::mutex> lock(m_cout);
		std::cout<<"Thread: "<<boost::this_thread::get_id()<<" gestopt"<<std::endl;
	}
}

void TestCircularBuffer::consumer() { // memberfunctie voor consumer thread
	{
		boost::lock_guard<boost::mutex> lock(m_cout);
		std::cout<<"Thread: "<<boost::this_thread::get_id()<<" gestart"<<std::endl;
	}
	for (int i(0); i<1000; ++i) {
		char c(b.get());
		{
			boost::unique_lock<boost::mutex> lock(m_cout);
			std::cout<<c;
		}
	}
	{
		boost::lock_guard<boost::mutex> lock(m_cout);
		std::cout<<"Thread: "<<boost::this_thread::get_id()<<" gestopt"<<std::endl;
	}
}

void TestCircularBuffer::run() { // run test
	boost::thread tc(&TestCircularBuffer::consumer, this);
	boost::thread tp1(&TestCircularBuffer::producer, this, 'k'); 
	boost::thread tp2(&TestCircularBuffer::producer, this, 'f'); 
	tp2.join();
	tp1.join();
	tc.join();
	if (!b.isEmpty()) {
	    boost::lock_guard<boost::mutex> lock(m_cout);
	    std::cout<<"Error: buffer is niet leeg!"<<std::endl;
	}
}

int main() {
	TestCircularBuffer test;
	test.run();
	std::cin.get();
	return 0; 
}