#include <boost/range/algorithm/nth_element.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/noncopyable.hpp>
#include <boost/timer/timer.hpp>
//#include <boost/timer.hpp>
#include <iostream>
#include <ostream>
#include <cstdlib>
#include <vector>
#include <ctime>
using namespace std;
using namespace boost;
// ______________________________ //
const int series = 33;
const int deepness = 5;
#define REPEATS 32
// ______________________________ //
bool error_check()
{
//return time(0) < 1;
static volatile bool t = false;
return t;
}
void *mallocator()
{
return malloc(4);
}
// ______________________________ //
class Holder : private noncopyable
{
void *data;
public:
Holder()
: data(mallocator())
{}
~Holder()
{
free(data);
}
};
template<int iter> struct exceptions
{
static void call()
{
#define EXP_REP(z, i, _) Holder h##i; exceptions<iter-1>::call();
BOOST_PP_REPEAT(REPEATS,EXP_REP,t)
}
};
template<> struct exceptions<0>
{
static void call()
{
if(error_check()) throw false;
}
};
// ______________________________ //
template<int iter> struct ifgoto
{
static bool call()
{
bool result = true;
#define IFG_REP0(z, i, _) void *d##i;
BOOST_PP_REPEAT(REPEATS,IFG_REP0,t)
#define IFG_REP1(z, i, _) d##i = mallocator(); if(! (result=ifgoto<iter-1>::call()) ) goto ERROR##i;
BOOST_PP_REPEAT(REPEATS,IFG_REP1,t)
#define IFG_REP_AUX(i) BOOST_PP_CAT(ERROR,i): free(BOOST_PP_CAT(d,i));
#define IFG_REP2(z, i, _) IFG_REP_AUX( BOOST_PP_SUB(BOOST_PP_SUB(REPEATS,1),i) )
BOOST_PP_REPEAT(REPEATS,IFG_REP2,t)
return result;
}
};
template<> struct ifgoto<0>
{
static bool call()
{
return error_check() == false;
}
};
// ______________________________ //
template<template<int> class test_case>
void test(const char *name)
{
cout << name;
vector<double> times;
for(int i=0;i!=series;++i)
{
//timer t;
timer::cpu_timer t;
test_case<deepness>::call();
times.push_back(double(t.elapsed().user));
}
vector<double>::iterator median = times.begin() + times.size()/2;
nth_element(times,median);
cout << "\tmedian is " << (*median)*1e-6 << "ms" << endl;
}
int main()
{
try
{
for(int i=0;i!=2;++i)
{
test<exceptions>("exceptions");
test<ifgoto>("if-error-goto");
}
}
catch(...){}
}