#include <iostream>
#include <string>
#include <thread>
#include <chrono>

using namespace std::chrono_literals;


class Thread
{
public:

	Thread(const std::string& _name)
		: m_name(_name)
		, m_running(false)
		, m_thread(nullptr)
	{}

	virtual void threadCode() = 0;

private:

	void _threadCode()
	{
		try
		{
			threadCode();
		}
		catch(const std::exception& e)
		{
			std::cerr << "exception in thread " << m_name << ": " << e.what();
		}
	}

public:

	void start()
	{
		m_running = true;
		m_thread = std::make_unique<std::thread>(&Thread::_threadCode, this);
	}

	void stop()
	{
		m_running = false;
		m_thread->join();
		m_thread.reset();
	}

	bool running()
	{
		return m_running;
	}

	const std::string& name()
	{
		return m_name;
	}

private:

	std::string m_name;
	bool m_running;
	std::unique_ptr<std::thread> m_thread;
};


class Enumerator : public Thread
{
public:

	Enumerator(int i)
		: Thread("Enumerator " + std::to_string(i))
		, m_i(i)
	{}

	void threadCode() override
	{
		while(running())
		{
			std::cout << m_i++ << "\n";
			std::this_thread::sleep_for(1000ms);
		}
	}

private:

	int m_i;
};


int main()
{
	Enumerator t1(0);
	Enumerator t2(100);

	t1.start();
	std::this_thread::sleep_for(500ms);
	t2.start();
	std::this_thread::sleep_for(10000ms);
	t1.stop();
	t2.stop();

	std::cout << "ich habe fertig\n";
}