#include <stdio.h>
#include <sys/time.h>
#include <time.h>

using namespace std;

#define NB 1000000

struct timeval add_time(struct timeval t1, struct timeval t2)
{
	struct timeval t;
	t.tv_sec = t1.tv_sec + t2.tv_sec;
	t.tv_usec = t1.tv_usec + t2.tv_usec;
	if (t.tv_usec > 1000000)
	{
		t.tv_usec -= 1000000;
		t.tv_sec += 1;
	}
	return t;
}
struct timeval sub_time(struct timeval t1, struct timeval t2)
{
	struct timeval t;
	t.tv_sec = t1.tv_sec - t2.tv_sec;
	if (t1.tv_usec < t2.tv_usec)
	{
		t1.tv_usec += 1000000;
		t.tv_sec -= 1;
	}
	t.tv_usec = t1.tv_usec - t2.tv_usec;
	return t;
}

float float_of_time(struct timeval t)
{
	return (float)t.tv_sec + (float)t.tv_usec / 1000000.;
}

struct timeval test1()
{
	struct timeval t1,t2;
	gettimeofday(&t1,NULL);
	for (int i = 0; i < NB; i++)
	{
		try
		{
			throw(0);
		}
		catch(int a)
		{
			(void)(a);
		}
	}
	gettimeofday(&t2,NULL);
	return sub_time(t2,t1);
}

void g()
{
	throw(0);
}

struct timeval test2()
{
	struct timeval t1,t2;
	gettimeofday(&t1,NULL);
	for (int i = 0; i < NB; i++)
	{
		try
		{
			g();
		}
		catch(int a)
		{
			(void)(a);
		}
	}
	gettimeofday(&t2,NULL);
	return sub_time(t2,t1);
}

struct timeval test3()
{
	struct timeval t1,t2;
	gettimeofday(&t1,NULL);
	for (int i = 0; i < NB; i++)
	{
		try
		{
			try
			{
				throw(0);
			}
			catch(float f)
			{
				(void)(f);
			}
		}
		catch(int a)
		{
			(void)(a);
		}
	}
	gettimeofday(&t2,NULL);
	return sub_time(t2,t1);
}

void h10()
{
	throw(0);
}
void h9()
{
	h10();
}
void h8()
{
	h9();
}
void h7()
{
	h8();
}
void h6()
{
	h7();
}
void h5()
{
	h6();
}
void h4()
{
	h5();
}
void h3()
{
	h4();
}
void h2()
{
	h3();
}
void h1()
{
	h2();
}

struct timeval test4()
{
	struct timeval t1,t2;
	gettimeofday(&t1,NULL);
	for (int i = 0; i < NB; i++)
	{
		try
		{
			h1();
		}
		catch(int a)
		{
			(void)(a);
		}
	}
	gettimeofday(&t2,NULL);
	return sub_time(t2,t1);
}

int main()
{
	struct timeval t1,t2,t3,t4,t;
	t1 = test1();
	t2 = test2();
	t3 = test3();
	t4 = test4();
	t = add_time(t1,t2);
	t = add_time(t,t3);
	t = add_time(t,t4);
	printf("Benchmark C++ :\n");
	printf("  1) 1 000 000 d'exceptions                                 : %fs\n",float_of_time(t1));
	printf("  2) 1 000 000 d'exceptions dans une sous fonction          : %fs\n",float_of_time(t2));
	printf("  3) 1 000 000 d'exceptions passant au travers d'un handler : %fs\n",float_of_time(t3));
	printf("  4) 1 000 000 d'exception dans 10 sous fonctions           : %fs\n",float_of_time(t4));
	printf("  total : %f\n",float_of_time(t));
	return 0;
}
