#include "zthread/channel.h"
#include "zthread/channel_static.h"
#include <iostream>
#include <thread>
#define LOOP_TIMES 1
int del_count = 0;
int add_count = 0;
int cpy_count = 0;
int mov_count = 0;
using namespace std;
class object {
public:
	const char* name;
	int res;
public:
	~object() {
		char buf[1024];
		sprintf(buf, "~~~~ %d %x \n", ++del_count, (int)this);
		std::cout << buf;
	};
	object(const char* name, int res = 0) {
		this->name = name;
		this->res = res;
		char buf[1024];
		sprintf(buf, "++++ %d %x \n", ++add_count, (int)this);
		std::cout << buf;
	}
	object(object& obj) {
		char buf[1024];
		sprintf(buf, "cccc %d %x<--%x\n", ++cpy_count, (int)this, (int) & obj);
		std::cout << buf;
		this->name = obj.name;
		this->res = obj.res;
	}
	object(object&& obj) noexcept{
		char buf[1024];
		sprintf(buf, "mmmm %d %x<--%x\n", ++mov_count, (int)this, (int)&obj);
		std::cout << buf;
		this->name = obj.name;
		this->res = obj.res;
	}
};
void test1() {

	zstd::channel<object> ch(16);
	auto p = [&]() {
		for (int i = 0; i < LOOP_TIMES * 2; i++) {
			this_thread::sleep_for(chrono::milliseconds(1000));
			ch.release("hello",i);
		}
		std::cout << "product end " << ch.count() << "\n";
	};
	auto c = [&](int id) {
		for (int i = 0; i < LOOP_TIMES; i++) {
			this_thread::sleep_for(chrono::milliseconds(500));
			object obj = ch.acquire();
			int r = obj.res;
			char buf[1024];
			sprintf(buf, "recv %d %x head %d - %d\n", r, (int)&obj, ch.head() , ch.tail());
			std::cout << buf;
		}
		std::cout << "consume end " << ch.count() << "\n";
	};
	thread t1(p);
	thread t2(c, 1);
	thread t3(c, 2);
	t1.join();
	t2.join();
	t3.join();
	std::cout << "test1:: res " << ch.count() << std::endl;
}
void test2() {
	zstd::channel_static<object, 16> ch2;
	zstd::channel_static<object, 32> ch3;
	ch2.release("", 2);
	ch3.release("", 3);
	ch3.release("");
	ch2.release("");
}
int main() {
	test1();
	test2();
}