
#include <log.h>

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <vector>
#include <list>
#include <thread>
#include <atomic>
#include <algorithm>

#define EV_MULTIPLICITY 1
#define EV_SIGNAL_ENABLE 1
#define EV_ASYNC_ENABLE 1
#define EV_USE_FLOOR 1
#include <ev++.h>

#include <clock.h>
#include <zio.h>
#include <znet.h>

struct io_thread:ev::dynamic_loop
{
	std::atomic<bool> m_stop_flag{false};
	std::thread*m_thread;
	ev::async   m_async;
    ev::io   m_io;
    ev::timer m_timer;
	uint64_t    m_count;
	io_thread ()
	{
		m_count=0;
        //异步
		m_async.set(*this);
		m_async.set<io_thread,&io_thread::on_async>(this);
		m_async.start();
       //tiemr.. 
       //set loop
        m_timer.set(*this);
        m_timer.set<io_thread,&io_thread::on_timer>(this);

		m_thread=new std::thread(std::bind(&io_thread::run,this));
        m_timer.start(2,0);
	}

	void on_async()
	{
		if(m_stop_flag.load())
			ev::dynamic_loop::break_loop(ev::ALL);
			
		++m_count;
        std_info("on_async%d:%d",std::this_thread::get_id(),m_count);
	}
    void on_timer()
    {
        std_info("on_timer....");
        m_timer.start(2,0);
    }
	void run()
	{
		dynamic_loop::run(0);
		//log_info("thread exit.");
        std_info("thread exit.%d",std::this_thread::get_id());
	}

	void destroy()
	{
		m_thread->join();
		delete this;
	}

	void notify(int i)
	{
		if(i==0)
		{
			m_stop_flag.store(true);
		}
		m_async.send();
	}
private:
	~io_thread()
	{
		delete m_thread;
	}
};

int main()
{
//	log_init("log.ini");

	std::vector<io_thread*>   ivec;

	const int NUM_THREAD=4;

	for(int i=0;i<NUM_THREAD;i++)
	{
		ivec.push_back(new io_thread());
	}

	zclock c;
	uint64_t atps=0;
	uint64_t tps=0;

	for(uint64_t i=1;i<1e8;i++)
	{
		for(auto&t:ivec)
		{
			tps++;
			atps++;
			t->notify(i);
		}

		if((i-1)%1000==0 && c.count_ms()>1000)
		{
			std_info("tps=%ld,all=%ld",tps,atps);
			tps=0;
			c.reset();
		}
	}

	std::for_each(ivec.begin(),ivec.end(),[](io_thread*i){
		i->notify(0);
		i->destroy();
		std_info("thread_counter=%d",i->m_count);
	});
	
	return 0;
}

