Я пытаюсь создать простую функцию таймера / профилировщика. Моя главная цель - создать функцию, которую я могу быстро, легко и незаметно добавить к любым вызовам функций, которые я хочу профилировать.
Так, например, для профилирования foo
, bar
и baz
Я хочу иметь функцию ft
(таймер функций), которая может выполнять следующие действия, воздействуя как можно меньше на исходный код:
ft(foo());
ft(bar(1, 2, 3));
int result = ft(baz());
string result = ft(qux("a", 2, 3.4));
Обратите внимание, что в случае baz
и qux
результат, возвращаемый из ft
, должен быть тем, что возвращают сами функции.
ft
обрабатывает все сроки и протоколирование и т. Д.
Я сталкивался с несколькими потоками, в которых упоминается, как выполнять обратные вызовы функций для функций с произвольными аргументами, но не так много, в которых даже упоминается, как обрабатывать возвращаемое значение.
Это самое близкое: Переменное число аргументов (va_list) с обратным вызовом функции? , но я завязал узлы при попытке обработать пустые функции, а также функции, возвращающие значение.
Я начинаю думать, что использование макросов - это способ сделать это, но, возможно, есть лучший способ.
Вот моя текущая слабая попытка (сокращенно):
static Timer fTimer;
class VoidFuncBase
{
public:
virtual void operator()() = 0;
};
class VoidFuncWrapper0 : public VoidFuncBase
{
public:
typedef void (*func)();
VoidFuncWrapper0(func fp) : fp_(fp) { }
void operator()() { fp_(); }
private:
func fp_;
};
template<typename P1>
class VoidFuncWrapper1 : public VoidFuncBase
{
public:
typedef void (*func)(const P1 &);
VoidFuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
void operator()() { fp_(p1_); }
private:
func fp_;
P1 p1_;
};
template<typename P1, typename P2>
class VoidFuncWrapper2 : public VoidFuncBase
{
public:
typedef void (*func)(const P1 &, const P2 &);
VoidFuncWrapper2(func fp, const P1 &p1, const P2 &p2)
: fp_(fp), p1_(p1), p2_(p2) { }
void operator()() { fp_(p1_, p2_); }
private:
func fp_;
P1 p1_;
P2 p2_;
};
template<typename R>
class FuncBase
{
public:
virtual R operator()() = 0;
};
template<typename R>
class FuncWrapper0 : public FuncBase<R>
{
public:
typedef R (*func)();
FuncWrapper0(func fp) : fp_(fp) { }
R operator()() { return fp_(); }
private:
func fp_;
};
template<typename R, typename P1>
class FuncWrapper1 : public FuncBase<R>
{
public:
typedef R (*func)(const P1 &);
FuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
R operator()() { return fp_(p1_); }
private:
func fp_;
P1 p1_;
};
template<typename R, typename P1, typename P2>
class FuncWrapper2 : public FuncBase<R>
{
public:
typedef R (*func)(const P1 &, const P2 &);
FuncWrapper2(func fp, const P1 &p1, const P2 &p2)
: fp_(fp), p1_(p1), p2_(p2) { }
R operator()() { return fp_(p1_, p2_); }
private:
func fp_;
P1 p1_;
P2 p2_;
};
template<typename R>
R ft(FuncBase<R> func, std::string functionName)
{
unsigned long threadId = getThreadId();
double startTimeMs = fTimer.getMilliseconds();
R result = func();
double duration = fTimer.getMilliseconds() - startTimeMs;
logf("%u %s took %fms", threadId, functionName.c_str(), duration);
return result;
}
void ft(VoidFuncBase func, std::string functionName, int logTimeoutMs)
{
unsigned long threadId = getThreadId();
double startTimeMs = timer.getMilliseconds();
func();
double duration = timer.getMilliseconds() - startTimeMs;
logf("%u %s took %fms", threadId, functionName.c_str(), duration);
}
В настоящее время я получаю
"ошибка: невозможно объявить параметр 'func' как абстрактный тип
"VoidFuncBase».
Но я, вероятно, все равно иду в неправильном направлении.