1253 lines
40 KiB
MQL5
1253 lines
40 KiB
MQL5
#property version "5.03"
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Include debugging library
|
|
//
|
|
// Select operational mode:
|
|
//
|
|
// - #define LIB_DEBUG
|
|
// -> This will disable LIB_PERF_PROFILING and enable DEBUGGING extensions
|
|
//
|
|
// - #define LIB_MQLAPI_TRACE
|
|
// -> This will enable the MQL API tracer module. Every call to an MQL API fnction will be
|
|
// logged to expert-journal. Also tracing of the _LastError is done.
|
|
//
|
|
// - #define LIB_PERF_PROFILING
|
|
// -> This will enable PERF_PROFILING macros. Only available in "runtime"-mode compilation.
|
|
// If trying to measure these metrics while "_DEBUG" or "LIB_DEBUG" is defined will not work.
|
|
//
|
|
// Define these before you include the library, as they define the included parts of the library.
|
|
//
|
|
// LIB_DEBUG, LIB_DEBUG_AUTOENABLE, LIB_DEBUG_MQLAPI_TRACE and
|
|
// LIB_MQLAPI_TRACE are superior to LIB_PERF_PROFILING and will disable LIB_PERF_PROFILING.
|
|
//
|
|
//
|
|
// Additional options for LIB_DEBUG
|
|
//
|
|
// LIB_DEBUG_AUTOENABLE
|
|
//
|
|
// This flag will make the library switch between runtime and debugging mode, depending on
|
|
// the compiler target. - This will imply LIB_DEBUG automatically as appropiate.
|
|
//
|
|
// LIB_DEBUG_MQLAPI_TRACE
|
|
//
|
|
// MQL API function call tracing support. This will log calls to built-in functions.
|
|
// "LIB_DEBUG_MQLAPI_TRACE" will enable this feature. YOu will get trace output, if you have
|
|
// LIB_DEBUG built-in tracing for the particular function enabled. - See example below on how to
|
|
// make a function traceable.
|
|
//
|
|
// Functions in which the tracing is activated, see description below, will now
|
|
// also log calls to MQL-API functions. The error code and return type will be logged.
|
|
//
|
|
// If you wish this feature to be enabled regardless of function tracing, you may define the flag
|
|
// "LIB_MQLAPI_TRACE". Now all calls to MQL-API get logged and checked. If this is
|
|
// activated, "LIB_DEBUG_MQLAPI" is implicated automatically, if LIB_DEBUG or LIB_DEBUG_AUTOENABLE
|
|
// is active.
|
|
//
|
|
// LIB_DEBUG_LOGFILE
|
|
//
|
|
// Debugging library supports output logging to file. This feature can be enabled by defining
|
|
// "LIB_DEBUG_LOGFILE" as shown below. (Automatically also defines LIB_DEBUG)
|
|
// Logs will be written to Common/* directory.
|
|
//
|
|
// This feature supports debug logging within optimizer runs of the program.
|
|
//
|
|
// LIB_DEBUG_NO_JOURNAL_OUTPUT
|
|
//
|
|
// Additionally the expert-journal output can be surpressed, separating the logs into two
|
|
// targets. - This way logging debug output and logging terminal output is separated.
|
|
//
|
|
// Define "LIB_DEBUG_NO_JOURNAL_OUTPUT" to disable expert-journal output from this library.
|
|
//
|
|
//
|
|
// Additional options for LIB_DEBUG_MQLAPI_TRACE and LIB_MQLAPI_TRACE
|
|
//
|
|
// To always print input parameters to a function, define
|
|
// LIB_MQLAPI_TRACE_SHOW_PARAMS.
|
|
//
|
|
// This will force printing of all input parameters
|
|
// which are not output parameters only.
|
|
//
|
|
// LIB_MQLAPI_TRACE_SHOW_RESULT
|
|
//
|
|
// This will force printing of results from the function call, including
|
|
// current error state
|
|
//
|
|
//
|
|
// !!! IMPORTANT NOTE !!!
|
|
//
|
|
// MQLAPI_TRACE and LIB_DEBUG_MQLAPI_TRACE is incompatible with the standard library from MQL.
|
|
// Work to resolve this issue is underway, but might take quite a while.
|
|
//
|
|
// Until then, if you are using any includes from standard library, you cannot activate
|
|
// the MQLAPI tracer module. - You will get compiler errors.
|
|
//
|
|
// Same goes for any function you created on your own, that shares a name with any of
|
|
// the functions provided by MQL-API.
|
|
//
|
|
// The tracer uses macro substitution to replace and intercept the calls to the API.
|
|
// Therefore any function with the same name as listed in the file
|
|
// "MQLplus/lib_debug/lib_debug_mqlapi_tracer_overwrite_macros.mqh"
|
|
// will confuse the compiler and library. You will not be able to compile your code.
|
|
//
|
|
// If it is mandatory for you to do so anyways, you need to setup a custom config
|
|
// for your project. - See below.
|
|
//
|
|
// !!! END !!!
|
|
//
|
|
//
|
|
// Customization for project specific needs
|
|
//
|
|
// If you wish to customize the library, this can be done easily. Procedure is described in
|
|
// "MQLplus/lib_debug/lib_debug_CustomConfig.mqh"
|
|
//
|
|
// See details in that file to customize lib_debug to your needs.
|
|
//
|
|
//
|
|
//
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Functions defined before include of lib_debug
|
|
//
|
|
template <typename T>
|
|
int MyArraySort(T& array[])
|
|
{ return(0); };
|
|
|
|
void MyPersonalVoidFunc(int arg01, int arg02, int arg03, int arg04, int arg05, int arg06, datetime arg07, string& arg08, color arg09, double arg10)
|
|
{ return; };
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////
|
|
//
|
|
// Include the library
|
|
//
|
|
//#define LIB_DEBUG
|
|
//#define LIB_DEBUG_AUTOENABLE
|
|
//#define LIB_DEBUG_LOGFILE
|
|
//#define LIB_DEBUG_NO_JOURNAL_OUTPUT
|
|
//#define LIB_DEBUG_MQLAPI_TRACE
|
|
#define LIB_MQLAPI_TRACE
|
|
//#define LIB_MQLAPI_TRACE_PERFORMANCE
|
|
//#define LIB_MQLAPI_TRACE_SHOW_PARAMS
|
|
//#define LIB_MQLAPI_TRACE_SHOW_RESULT
|
|
//#define LIB_PERF_PROFILING
|
|
#include "lib_debug_CustomConfig.mqh"
|
|
//#include <MQLplus/lib_debug.mqh>
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In OnInit you can see a simple usage of the debugging macros.
|
|
//
|
|
// We will only use some stand-alone macros for quick debugging.
|
|
//
|
|
// DBG_MSG()
|
|
// DBG_MSG_VAR()
|
|
// DBG_MSG_VAR_IF()
|
|
// DBG_MSG_PERSIST()
|
|
// DBG_MSG_BITS()
|
|
// DBG_MSG_ERRCODE()
|
|
//
|
|
// These macros support all built-in datatypes (also in form of arrays).
|
|
// (unsigned) char, short, int, long
|
|
// bool, datetime, color, complex, matrix(f/c), vector(f/c),
|
|
// float, double,
|
|
// string, enum, struct, class and interface as well as pointers.
|
|
//
|
|
//
|
|
// And MQL structures:
|
|
// MqlDateTime, MqlRates, MqlTick, MqlParam, MqlBookInfo,
|
|
// MqlTradeRequest, MqlTradeCheckResult, MqlTradeResult,
|
|
// MqlTradeTransaction,
|
|
// MqlCalendarCountry, MqlCalendarEvent, MqlCalendarValue,
|
|
// DXVector, DXVertexLayout
|
|
//
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Custom function tracing, see
|
|
// lib_debug/lib_debug_CustomConfig.mqh
|
|
//
|
|
double some_array[];
|
|
int return_val = MyArraySort(some_array);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Simple output macros
|
|
//
|
|
|
|
// Some initial debug message
|
|
DBG_MSG("Example how to use lib_debug.mqh");
|
|
|
|
// Output details about current program
|
|
// Available in debugging and runtime
|
|
printf("%s", DBG_STR_EX45_FILEINFO);
|
|
|
|
// Keep this message also in runtime builds
|
|
DBG_MSG_PERSIST("Persistent message in debug and runtime (Runtime is without debug details)");
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// All basic output macros available
|
|
//
|
|
|
|
// Get output from library as string
|
|
ulong test_var = LONG_MAX;
|
|
string test = NULL;
|
|
|
|
// Macros will be preserved in runtime version but resolve to ((string)NULL)
|
|
test = DBG_STR("Test A");
|
|
test = DBG_STR_VAR(_LastError);
|
|
test = DBG_STR_VAR(test_var);
|
|
test = DBG_STR_VAR_IF(true, test_var);
|
|
test = DBG_STR_PERSIST("Some message");
|
|
test = DBG_STR_BITS(test_var);
|
|
test = DBG_STR_ERRCODE(5004);
|
|
|
|
// These will be completley removed from runtime builds
|
|
DBG_MSG("Test A");
|
|
DBG_MSG_VAR(_LastError);
|
|
DBG_MSG_VAR(test_var);
|
|
DBG_MSG_VAR_IF(true, test_var);
|
|
DBG_MSG_PERSIST("Some message");
|
|
DBG_MSG_BITS(test_var);
|
|
DBG_MSG_ERRCODE(5004);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// IEEE754 printing
|
|
//
|
|
|
|
// Verify correct printing of IEEE754 data
|
|
Print("Check floats:");
|
|
Print( 0.1f + 0.6f );
|
|
Print( 0.7f );
|
|
DBG_MSG(string((float)0.1 + (float)0.6));
|
|
DBG_MSG_VAR(0.1f + 0.6f);
|
|
DBG_MSG_VAR(0.7f);
|
|
DBG_MSG_VAR(FLT_MIN);
|
|
DBG_MSG_VAR(FLT_MAX);
|
|
|
|
Print("Check doubles:");
|
|
Print( 0.1 + 0.2);
|
|
Print( 0.3 );
|
|
DBG_MSG(string(0.1 + 0.2));
|
|
DBG_MSG_VAR(0.1 + 0.2);
|
|
DBG_MSG_VAR(0.3);
|
|
DBG_MSG_VAR(DBL_MIN);
|
|
DBG_MSG_VAR(DBL_MAX);
|
|
|
|
|
|
// Direct value printing
|
|
DBG_MSG_BITS((uint)123);
|
|
DBG_MSG_VAR(PRICE_CLOSE);
|
|
DBG_MSG_VAR(1);
|
|
DBG_MSG_VAR(true);
|
|
DBG_MSG_VAR(TimeCurrent());
|
|
DBG_MSG_VAR(clrBlue);
|
|
DBG_MSG_VAR("Print Me");
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// The flexibility of DBG_MSG_VAR and DBG_STR_VAR
|
|
//
|
|
|
|
// Output primitive variables
|
|
enum custom_enum
|
|
{
|
|
SOME_ENUM_VAL1,
|
|
SOME_ENUM_VAL2
|
|
};
|
|
custom_enum my_enum = SOME_ENUM_VAL2;
|
|
ENUM_APPLIED_PRICE e_val = PRICE_CLOSE;
|
|
char c_val = 1;
|
|
uchar uc_val = 2;
|
|
short s_val = 3;
|
|
int i_val = 4;
|
|
long l_val = 5;
|
|
bool b_val = true;
|
|
datetime d_val = TimeCurrent();
|
|
float flt_val = (float)1.61;
|
|
double dbl_val = 3.14;
|
|
color clr_val = clrAqua;
|
|
string str_val = "Some string";
|
|
complex cmplx_val = { 0.1, 0.2 };
|
|
vector v_val = { 0, 1, 2, 3 };
|
|
vectorf vf_val = { (float)0.1, (float)1.1, (float)2.1, (float)3.1 };
|
|
matrix m_val (1, 2);
|
|
matrixf mf_val (1.3, 2.3);
|
|
|
|
DBG_MSG_VAR(my_enum);
|
|
DBG_MSG_VAR(e_val);
|
|
DBG_MSG_VAR(c_val);
|
|
DBG_MSG_VAR(uc_val);
|
|
DBG_MSG_VAR(s_val);
|
|
DBG_MSG_VAR(i_val);
|
|
DBG_MSG_VAR(l_val);
|
|
DBG_MSG_VAR(b_val);
|
|
DBG_MSG_VAR(d_val);
|
|
DBG_MSG_VAR(flt_val);
|
|
DBG_MSG_VAR(dbl_val);
|
|
DBG_MSG_VAR(clr_val);
|
|
DBG_MSG_VAR(str_val);
|
|
DBG_MSG_VAR(_LastError);
|
|
|
|
#ifdef __MQL5__
|
|
complex c1 = { DBL_MIN, 0.2 };
|
|
complex c2 = { 0.3, DBL_MAX };
|
|
complex c3 = { 0.5, 0.6 };
|
|
complex c4 = { 0.6, 0.7 };
|
|
matrixc mc_val {{c1, c2}, {c3, c4}};
|
|
vectorc vc_val = { c1, c2, c3, c4 };
|
|
|
|
DBG_MSG_VAR(cmplx_val);
|
|
DBG_MSG_VAR(m_val);
|
|
DBG_MSG_VAR(mf_val);
|
|
DBG_MSG_VAR(mc_val);
|
|
DBG_MSG_VAR(v_val);
|
|
DBG_MSG_VAR(vf_val);
|
|
DBG_MSG_VAR(vc_val);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Print unknown objects, see function at the end.
|
|
//
|
|
|
|
// Example of printing objects
|
|
call_obj_function();
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Conditional execution of DBG_MSG() and DBG_MSG_VAR() macro
|
|
//
|
|
// Use DBG_MSG_IF() as shown below.
|
|
// Use DBG_MSG_VAR_IF() as shown below.
|
|
//
|
|
// NOTE: The fist statement is a boolean evaluation.
|
|
// It is encapuslated properly and therefore can
|
|
// be anything that evaluates to "true" or "false".
|
|
// Same rules apply as for an "if()" statement.
|
|
|
|
bool printme = true;
|
|
DBG_MSG_IF(printme, "This will only show, if a condition is true!");
|
|
DBG_MSG_VAR_IF(printme, TimeLocal());
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Print arrays
|
|
//
|
|
|
|
// Output arrays
|
|
int i_arr[50];
|
|
for(int cnt = NULL; (cnt < 50) && !_StopFlag; cnt++)
|
|
{ i_arr[cnt] = MathRand(); }
|
|
DBG_MSG_VAR(i_arr);
|
|
|
|
string str_val_arr[3];
|
|
DBG_MSG_VAR(str_val_arr);
|
|
|
|
#ifdef __MQL5__
|
|
matrixc mc_val1 {{c1, c2}, {c3, c4}};
|
|
matrixc mc_val2 {{c2, c1}, {c3, c4}};
|
|
matrixc mc_val3 {{c1, c2}, {c4, c3}};
|
|
matrixc mc_val_arr[3];
|
|
mc_val_arr[0] = mc_val1;
|
|
mc_val_arr[1] = mc_val2;
|
|
mc_val_arr[2] = mc_val3;
|
|
DBG_MSG_VAR(mc_val_arr);
|
|
|
|
#endif
|
|
|
|
// Output two arrays side by side
|
|
double d_arr[50];
|
|
for(int cnt = NULL; (cnt < 50) && !_StopFlag; cnt++)
|
|
{ d_arr[cnt] = MathRand(); }
|
|
DBG_MSG_LISTDUMP(i_arr, d_arr);
|
|
|
|
|
|
|
|
/////////////////////////////////////
|
|
//
|
|
// Access an array
|
|
//
|
|
// Check if it is accessible
|
|
//
|
|
// These macros will be replaced
|
|
// for runtime environment to their
|
|
// normal usage. - No overhead applied.
|
|
//
|
|
|
|
DBG_MSG_ARRAY_OUT_OF_RANGE(i_arr, 50);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Print structures and arrays of structures
|
|
//
|
|
|
|
// Output MQL structures
|
|
MqlDateTime mql_dtm;
|
|
MqlRates mql_rates;
|
|
MqlTick mql_tick;
|
|
MqlParam mql_param;
|
|
MqlBookInfo mql_book;
|
|
DBG_MSG_VAR(mql_dtm);
|
|
DBG_MSG_VAR(mql_rates);
|
|
DBG_MSG_VAR(mql_tick);
|
|
DBG_MSG_VAR(mql_param);
|
|
DBG_MSG_VAR(mql_book);
|
|
|
|
#ifdef __MQL5__
|
|
MqlTradeRequest mql_trade_request;
|
|
MqlTradeCheckResult mql_tradecheckresult;
|
|
MqlTradeResult mql_trade_result;
|
|
MqlTradeTransaction mql_transaction;
|
|
MqlCalendarCountry mql_cal_cntry;
|
|
MqlCalendarEvent mql_cal_event;
|
|
MqlCalendarValue mql_cal_value;
|
|
DXVector mql_dxvector;
|
|
DXVertexLayout mql_dxvertex;
|
|
DBG_MSG_VAR(mql_trade_request);
|
|
DBG_MSG_VAR(mql_tradecheckresult);
|
|
DBG_MSG_VAR(mql_trade_result);
|
|
DBG_MSG_VAR(mql_transaction);
|
|
DBG_MSG_VAR(mql_cal_cntry);
|
|
DBG_MSG_VAR(mql_cal_event);
|
|
DBG_MSG_VAR(mql_cal_value);
|
|
DBG_MSG_VAR(mql_dxvector);
|
|
DBG_MSG_VAR(mql_dxvertex);
|
|
|
|
#endif
|
|
|
|
|
|
// See the difference in type printed
|
|
DBG_MSG_VAR(EnumToString(mql_param.type));
|
|
DBG_MSG_VAR(mql_param.type);
|
|
DBG_MSG_VAR(mql_param.integer_value);
|
|
DBG_MSG_VAR(mql_param.double_value);
|
|
|
|
|
|
// Output arrays of structures
|
|
MqlDateTime arr_mql_dtm[3];
|
|
MqlRates arr_mql_rates[3];
|
|
MqlTick arr_mql_tick[3];
|
|
MqlParam arr_mql_param[3];
|
|
MqlBookInfo arr_mql_book[3];
|
|
DBG_MSG_VAR(arr_mql_dtm);
|
|
DBG_MSG_VAR(arr_mql_rates);
|
|
DBG_MSG_VAR(arr_mql_tick);
|
|
DBG_MSG_VAR(arr_mql_param);
|
|
DBG_MSG_VAR(arr_mql_book);
|
|
|
|
#ifdef __MQL5__
|
|
MqlTradeRequest arr_mql_trade_request[3];
|
|
MqlTradeCheckResult arr_mql_tradecheckresult[3];
|
|
MqlTradeResult arr_mql_trade_result[3];
|
|
MqlTradeTransaction arr_mql_transaction[3];
|
|
MqlCalendarCountry arr_mql_cal_cntry[3];
|
|
MqlCalendarEvent arr_mql_cal_event[3];
|
|
MqlCalendarValue arr_mql_cal_value[3];
|
|
DBG_MSG_VAR(arr_mql_trade_request);
|
|
DBG_MSG_VAR(arr_mql_tradecheckresult);
|
|
DBG_MSG_VAR(arr_mql_trade_result);
|
|
DBG_MSG_VAR(arr_mql_transaction);
|
|
DBG_MSG_VAR(arr_mql_cal_cntry);
|
|
DBG_MSG_VAR(arr_mql_cal_event);
|
|
DBG_MSG_VAR(arr_mql_cal_value);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Analyze condition statements
|
|
//
|
|
// Any complexity is supported.
|
|
// Applicable to all condition evaluations.
|
|
// if(), while(), for(), () ? : ; ....
|
|
//
|
|
|
|
if(DBG_MSG_EVAL(0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
if(DBG_MSG_EVAL_IF(printme, 0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
if(DBG_MSG_EVAL_CMNT("Check equality", 0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
if(DBG_MSG_EVAL_IF_CMNT(printme, "Check equality", 0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
|
|
printme = false;
|
|
if(DBG_MSG_EVAL_IF(printme, 0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
if(DBG_MSG_EVAL_IF_CMNT(printme, "Check equality", 0.1 + 0.2 == 0.3))
|
|
{ Print("true"); }
|
|
else
|
|
{ Print("false"); }
|
|
|
|
|
|
// Return
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In OnDeinit we will use full tracing of the function call.
|
|
//
|
|
// First we define some helpers for compile time code
|
|
// inclusion selection. This will make it easy to enable/disable
|
|
// function tracing as needed.
|
|
//
|
|
// To do this, first a macro is defined which will be used as a
|
|
// switch (defined = trace function) (not defined = disable tracing)
|
|
//
|
|
// We can collect these "switches" at top of file for a better overview
|
|
// Also we could wrap them into a condition, so that they will only be
|
|
// defined when debugging is enabled.
|
|
//
|
|
// Example:
|
|
// #ifdef LIB_DEBUG
|
|
// #define DBG_TRACE_EXPERT_MAIN_ONDEINIT
|
|
//
|
|
// #endif
|
|
|
|
// En/Disable function tracing by commenting following macro:
|
|
#define DBG_TRACE_EXPERT_MAIN_ONDEINIT
|
|
|
|
|
|
// Now we define the helper macros which will be used inside
|
|
// the functions body.
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function debug trace code
|
|
#ifdef DBG_TRACE_EXPERT_MAIN_ONDEINIT
|
|
#undef DBG_TRACE_EXPERT_MAIN_ONDEINIT
|
|
#define DBG_TRACE_EXPERT_MAIN_ONDEINIT(x) x
|
|
#define DBG_TRACE_EXPERT_MAIN_ONDEINIT_RETURN DBG_MSG_TRACE_RETURN
|
|
|
|
#else
|
|
#define DBG_TRACE_EXPERT_MAIN_ONDEINIT(x)
|
|
#define DBG_TRACE_EXPERT_MAIN_ONDEINIT_RETURN DBG_MSG_NOTRACE_RETURN
|
|
|
|
#endif
|
|
/////////////////////////////////////
|
|
void OnDeinit(const int reason)
|
|
{
|
|
/////////////////////////////////////
|
|
//
|
|
// TOP of function body
|
|
//
|
|
// Here the tracing code gets included, this is mandatory for tracing to work.
|
|
// The switching macro can also be used to include additional
|
|
// debugging code, if any is required, see example below.
|
|
DBG_TRACE_EXPERT_MAIN_ONDEINIT(
|
|
DBG_MSG_TRACE_BEGIN;
|
|
|
|
// Additional details can be added here, as required.
|
|
// For example to trace the inputs to this function, we can add
|
|
DBG_MSG_VAR(reason);
|
|
|
|
// Or whatever we would like to add.
|
|
);
|
|
|
|
// Additionally the macro "PERF_COUNTER_BEGIN" must be added.
|
|
// It is mandatory to complete the "return" macro, irrespective of it
|
|
// being used or not. (Any insertions will be removed for runtime builds,
|
|
// if "LIB_PERF_PROFILING" is not defined)
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
//
|
|
// This concludes the functions head
|
|
// control code required for tracing.
|
|
// If tracing is disabled for this function,
|
|
// all additional code will be stripped at
|
|
// compile time.
|
|
//
|
|
// Now follows the actual functions body:
|
|
/////////////////////////////////////
|
|
|
|
|
|
// Local init
|
|
|
|
int some_int_val = 3;
|
|
string some_string = "I dont know";
|
|
|
|
/////////////////////////////////////
|
|
//
|
|
// As an example, here the local variables
|
|
// are printed, but only if tracing is enbaled.
|
|
// In contrast to the usage of macros in OnInit, where
|
|
// the macros were not wrapped in the
|
|
// Trace-Enable-Disable macro.
|
|
//
|
|
DBG_TRACE_EXPERT_MAIN_ONDEINIT(
|
|
DBG_MSG_VAR(some_int_val);
|
|
DBG_MSG_VAR(some_string);
|
|
);
|
|
|
|
|
|
// Destroy timer
|
|
|
|
EventKillTimer();
|
|
|
|
|
|
|
|
/////////////////////////////////////
|
|
//
|
|
// EXITING/RETURNING from the fucntions body.
|
|
//
|
|
// A return statement is mandatory, no matter the functions signature.
|
|
// This will inform the debug library about the functions ending/exiting.
|
|
//
|
|
// The special function "OnDeinit" will auto-resolve the deinit reason
|
|
// and show the state of the _StopFlag/IsStopped() variable.
|
|
// This is automatically inserted and needs no extra care taking.
|
|
//
|
|
DBG_TRACE_EXPERT_MAIN_ONDEINIT_RETURN;
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In OnTick we will use full tracing of the function call as
|
|
// shown with OnDeinit, and we will integrate global performance
|
|
// counters as well. This will give output of the runtime used by
|
|
// this function.
|
|
//
|
|
// Since the tracing has already been exlained, here is a
|
|
// stripped version, showing the raw requirements for a full trace.
|
|
//
|
|
// Short outline.
|
|
// - First define the enable/disable macros.
|
|
// - Then include the head required inside the body.
|
|
// - Use the return macro at all exit points of the function.
|
|
//
|
|
// To enable tracing for this function, same procedure as
|
|
// with OnDeinit applies.
|
|
// Again, this could be collected at top of file for better oversight.
|
|
|
|
// Turn on tracing
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTICK
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function debug trace code
|
|
#ifdef DBG_TRACE_EXPERT_MAIN_ONTICK
|
|
#undef DBG_TRACE_EXPERT_MAIN_ONTICK
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTICK(x) x
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTICK_RETURN DBG_MSG_TRACE_RETURN
|
|
|
|
#else
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTICK(x)
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTICK_RETURN DBG_MSG_NOTRACE_RETURN
|
|
|
|
#endif
|
|
/////////////////////////////////////
|
|
void OnTick()
|
|
{
|
|
DBG_TRACE_EXPERT_MAIN_ONTICK(
|
|
DBG_MSG_TRACE_BEGIN;
|
|
);
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
// Local init
|
|
int some_var = MathRand();
|
|
|
|
|
|
|
|
// Some random check operation
|
|
if((some_var % 2) == 0)
|
|
{
|
|
call_sub_function();
|
|
call_sub2_function();
|
|
call_obj_function();
|
|
}
|
|
|
|
|
|
// Some eventual exit at annother point inside the functions body
|
|
if((some_var % 2048) == 0)
|
|
{ DBG_TRACE_EXPERT_MAIN_ONTICK_RETURN; }
|
|
|
|
|
|
// Return
|
|
DBG_TRACE_EXPERT_MAIN_ONTICK_RETURN;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In OnTimer we will use only the performance metrics macros.
|
|
//
|
|
// For ease of use, a return macro will be defined. This is the
|
|
// only requirement for performance metrics to be displayed in the
|
|
// experts journal.
|
|
//
|
|
// Performance macros are enabled only in release versions
|
|
// of the code, they are disabled inside of debugging environments.
|
|
//
|
|
// Debugging environment is defined by the flag LIB_DEBUG.
|
|
// To enable performance macros, define LIB_PERF_PROFILING.
|
|
//
|
|
// NOTE:
|
|
// The macro "DBG_MSG_TRACE_RETURN" or "DBG_MSG_NOTRACE_RETURN"
|
|
// must be used, so the performance control block will be properly closed.
|
|
// Therefore we define relevant macros again, as shown in other examples.
|
|
//
|
|
// Enable/disable tracing does not influence the perfomrance macros, as tracing
|
|
// is only enabled when "LIB_DEBUG" is defined and "PERF_*"-macros are disabled.
|
|
// You will get performance measurements when the global macro "LIB_PERF_PROFILING"
|
|
// is defined and the global macro "LIB_DEBUG" is not defined.
|
|
//
|
|
//
|
|
// We can now define additional, custom performance blocks on a global level.
|
|
// These work accross functions and can be used to trace certain parts of the
|
|
// code. - Each block has its own call counter, therefore it is not advised
|
|
// to reuse the blocks for different code sections, except of course thats
|
|
// exactly what you want to measure.
|
|
//
|
|
// These blocks may overlap, if required. - It is necessary t ounderstand,
|
|
// when doing so, you will also measure the times each macro takes. The execution
|
|
// of these macros would be part of your measurement.
|
|
//
|
|
// See example below.
|
|
//
|
|
|
|
// Create additional performance counters
|
|
// IDs can be specified freely
|
|
PERF_COUNTER_DEFINE_ID(on_timer_for_loop);
|
|
|
|
// Additional example (these are not used)
|
|
PERF_COUNTER_DEFINE_ID(if_g_func);
|
|
PERF_COUNTER_DEFINE_ID(call_f3_func);
|
|
PERF_COUNTER_DEFINE_ID(printf_f1);
|
|
PERF_COUNTER_DEFINE_ID(printf_f2);
|
|
|
|
// Performance block IDs can be created on a global scope as well
|
|
// as on function local scope and even in code blocks inside of
|
|
// functions scope.
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function performance trace code
|
|
#define DBG_TRACE_EXPERT_MAIN_ONTIMER_RETURN DBG_MSG_NOTRACE_RETURN
|
|
|
|
/////////////////////////////////////
|
|
void OnTimer()
|
|
{
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
// Measuring a loop
|
|
double sum = NULL;
|
|
|
|
PERF_COUNTER_BEGIN_ID(on_timer_for_loop);
|
|
for(int cnt = NULL; (cnt < 1000000) && !_StopFlag; cnt++)
|
|
{
|
|
sum += 1.0;
|
|
}
|
|
PERF_COUNTER_END_ID(on_timer_for_loop);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Here an example of possible nested performance blocks.
|
|
// This example is very theoretical, but shows how blocks can be applied.
|
|
//
|
|
|
|
// Local scope
|
|
{
|
|
// These definitions can be on any scope in
|
|
// the hirarchy above this scope of the function all
|
|
// the way up to the global scope.
|
|
PERF_COUNTER_DEFINE_ID(a_local_scope);
|
|
PERF_COUNTER_DEFINE_ID(nested_level_1);
|
|
PERF_COUNTER_DEFINE_ID(overlapping_block_a);
|
|
PERF_COUNTER_DEFINE_ID(overlapping_block_b);
|
|
|
|
|
|
// Begin measurement of most outer block
|
|
PERF_COUNTER_BEGIN_ID(a_local_scope);
|
|
|
|
// Have some code here (not mandatory)
|
|
|
|
|
|
// Nested performance block 1
|
|
PERF_COUNTER_BEGIN_ID(nested_level_1);
|
|
|
|
// Have more code here
|
|
|
|
|
|
// Overlapping execution block
|
|
PERF_COUNTER_BEGIN_ID(overlapping_block_a);
|
|
|
|
// test unbraced if statements
|
|
if(!MathIsValidNumber(1.23))
|
|
Print("number is non valid");
|
|
else
|
|
Print("valid");
|
|
|
|
// test nested api function calls
|
|
if(MathIsValidNumber(MathRand()))
|
|
Print("number is valid");
|
|
|
|
// test unary operators
|
|
if(!MathIsValidNumber(MathRand()))
|
|
Print("number is non valid");
|
|
|
|
// test void api function
|
|
srand(GetTickCount());
|
|
|
|
// test complex expressions + operator precedence rules
|
|
Print(MathRand() + MathRand() * GetTickCount());
|
|
|
|
// test unbraced for statements + explicit typecast
|
|
for(int i = 0; i < 2; i++)
|
|
(int) floor(log10(rand()));
|
|
|
|
// test accuracy of printing doubles
|
|
Print(MathAbs(0.3));
|
|
Print(MathAbs(0.1 + 0.2));
|
|
|
|
|
|
// Open next block
|
|
PERF_COUNTER_BEGIN_ID(overlapping_block_b);
|
|
|
|
// test accuracy of printing floats
|
|
Print(MathAbs(0.7f));
|
|
Print(MathAbs(0.1f + 0.6f));
|
|
|
|
// test typename bug for namespace identifiers.
|
|
Print(typename((GetTickCount())));
|
|
Print(sizeof(GetTickCount()));
|
|
|
|
// test error codes from unsuccessful api function calls
|
|
FileOpen("file.xyz", FILE_READ);
|
|
|
|
int hdbase = DatabaseOpen("db.sqlite", DATABASE_OPEN_READONLY);
|
|
DatabaseClose(hdbase);
|
|
|
|
// test correct type promotion of ternary operator.
|
|
#define tern_expr (true ? MathMax(101, 201) : MathMax("a", "b"))
|
|
Print(tern_expr); // compiler warning: implicit conversion from 'number' to 'string' (This is correct behaviour!)
|
|
Print(typename(tern_expr));
|
|
|
|
// test api function that returns an enumerated value
|
|
int period = Period();
|
|
|
|
// test overloads of one api function
|
|
double ask = SymbolInfoDouble(NULL, SYMBOL_ASK);
|
|
SymbolInfoDouble(NULL, SYMBOL_ASK, ask);
|
|
|
|
|
|
// Now closing block A
|
|
PERF_COUNTER_END_ID(overlapping_block_a);
|
|
|
|
// Some code for block B
|
|
|
|
|
|
// Now closing block B
|
|
PERF_COUNTER_END_ID(overlapping_block_b);
|
|
|
|
// Maybe more code here for nested level 1
|
|
|
|
|
|
// Close nested block 1
|
|
PERF_COUNTER_END_ID(nested_level_1);
|
|
|
|
// Optionally have code here as well....
|
|
|
|
|
|
// Close most outer block
|
|
PERF_COUNTER_END_ID(a_local_scope);
|
|
}
|
|
|
|
|
|
// The above example will also measure the performance counters itself.
|
|
// Although they are held as short as possible, code-wise, it will
|
|
// have some influence on the pure code thats being measured.
|
|
//
|
|
// The impact can vary, depending on the memory-paging that happens
|
|
// by accessing different areas of memory. - The variations will be
|
|
// within the margins of error and therefore can (mostly) be ignored.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Standalone performance macros example
|
|
//
|
|
// To measure certain parts of code in a standalone environment,
|
|
// following macros are implemented to do this.
|
|
//
|
|
// There are three variations of this macro available. Depending on
|
|
// the return value of the function to be measured, either having
|
|
// a return value, a return object or not having a return value, you
|
|
// need to use the appropiate macro.
|
|
//
|
|
// PERF_COUNTER_TIMEIT_V (V = void)
|
|
// This macro is used to measure functions or function sequences
|
|
// that do not have a return value.
|
|
//
|
|
// PERF_COUNTER_TIMEIT_R (R = return)
|
|
// This macro will return the resulting value (return value)
|
|
// of the function being called, or their combination of such.
|
|
// For a better understanding, see the examples below.
|
|
//
|
|
// PERF_COUNTER_TIMEIT_O (O = Object)
|
|
// This macro will return the object (returned by the function)
|
|
// of the function being called.
|
|
//
|
|
// NOTE:
|
|
//
|
|
// PERF_COUNTER_TIMEIT_V may not be mentioned more than once per line of code.
|
|
// Internally the macro uses the __LINE__ macro for identifying the call,
|
|
// therefore it is mandatory to have only one call per code line.
|
|
// Also be aware, if including this macro inside of another macro, all
|
|
// statements will be on one line of code.
|
|
//
|
|
// PERF_COUNTER_TIMEIT_R uses the complier macro __COUNTER__ to identify
|
|
// unique its callings. Be aware, in case you rely on the sequence of
|
|
// counting provided by __COUNTER__ within your code. Each mentioning of
|
|
// the macro "PERF_COUNTER_TIMEIT_R" will increase the __COUNTER__ by one.
|
|
//
|
|
// PERF_COUNTER_TIMEIT_O notes are same as for PERF_COUNTER_TIMEIT_R, with
|
|
// one addition: The Copy-Constructor of the returned object will be called
|
|
// twice. The first call contributes to the measurement results, the second
|
|
// consequently does not. In order to encapusalte the function calls, an
|
|
// additional copy of the object is required within the process of returning
|
|
// values from the function.
|
|
//
|
|
// For pointers as return value, either macro "PERF_COUNTER_TIMEIT_R" or
|
|
// "PERF_COUNTER_TIMEIT_O" can be used. - Both work the same way in this case.
|
|
//
|
|
|
|
// A single function call
|
|
PERF_COUNTER_TIMEIT_V(
|
|
printf("Some text A");
|
|
);
|
|
|
|
// A block sequence of function calls
|
|
PERF_COUNTER_TIMEIT_V(
|
|
printf("Some text B");
|
|
printf("Some text C");
|
|
);
|
|
|
|
|
|
// Example of complex measurements
|
|
b_start();
|
|
|
|
|
|
// Return
|
|
DBG_TRACE_EXPERT_MAIN_ONTIMER_RETURN;
|
|
}
|
|
|
|
|
|
|
|
|
|
int f1() { Sleep(100); return(1); }
|
|
int f2() { Sleep(200); return(2); }
|
|
int f3() { Sleep(300); return(3); }
|
|
|
|
int g()
|
|
{
|
|
return(PERF_COUNTER_TIMEIT_R(f1() + f2() + f3() == 6) ?
|
|
PERF_COUNTER_TIMEIT_R(f1() * f2()) : 0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Service program start function |
|
|
//+------------------------------------------------------------------+
|
|
void b_start()
|
|
{
|
|
if (PERF_COUNTER_TIMEIT_R(g()) == 2)
|
|
{
|
|
PERF_COUNTER_TIMEIT_V(
|
|
Print(f3() == 3);
|
|
);
|
|
}
|
|
|
|
PERF_COUNTER_TIMEIT_V(
|
|
Print(f1());
|
|
);
|
|
|
|
PERF_COUNTER_TIMEIT_V(
|
|
Print(f2());
|
|
);
|
|
|
|
return;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// In call_sub_function we will use full tracing of the function call.
|
|
//
|
|
// This example shows the difference for a function with
|
|
// a return value.
|
|
//
|
|
// Take notice of the used macros. - It is required to use a
|
|
// different return macro for this type of function call.
|
|
//
|
|
// Instead of using the macro "DBG_MSG_TRACE_RETURN" and "DBG_MSG_NOTRACE_RETURN"
|
|
// here the macros "DBG_MSG_TRACE_RETURN_VAR(x)" and "DBG_MSG_NOTRACE_RETURN_VAR(x)"
|
|
// are used.
|
|
//
|
|
// For use of objects of type "struct", "class" or "interface", a separate
|
|
// return value macro must be used. - (This implementation is new in MQL5)
|
|
//
|
|
// Returning objects from functions, use following macros:
|
|
// "DBG_MSG_TRACE_RETURN_OBJ(x)" and "DBG_MSG_NOTRACE_RETURN_OBJ(x)"
|
|
//
|
|
// For use with pointers as return value, either macro can be used, preferably use
|
|
// "DBG_MSG_TRACE_RETURN_VAR(x)".
|
|
//
|
|
// IMPORTANT NOTICE:
|
|
// Calling the macro with the parameter "NULL" requires!!! a cast operation.
|
|
// (This functions return value is "int", "const int" or "int" doesnt make a difference)
|
|
//
|
|
// Example:
|
|
// DBG_MSG_TRACE_RETURN_VAR((int)NULL);
|
|
//
|
|
// This cast operation can be included in the macro definition itself, like this:
|
|
// #define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN(x) DBG_MSG_TRACE_RETURN_VAR((int)x)
|
|
// #define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x)
|
|
//
|
|
// or inside the function using the custom defined macro:
|
|
// DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN((int)NULL);
|
|
//
|
|
// See second function example below.
|
|
// Here the cast operation is inside the functions body.
|
|
// NOTE: The runtime macro does not require the cast operation.
|
|
//
|
|
// Again the enbale trace macro needs to be defined, so tracing
|
|
// is enabled.
|
|
|
|
// Enable tracing of this function
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Example function with return value |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function debug trace code
|
|
#ifdef DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION
|
|
#undef DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION(x) x
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x)
|
|
|
|
#else
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION(x)
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x)
|
|
|
|
#endif
|
|
/////////////////////////////////////
|
|
const int call_sub_function()
|
|
{
|
|
DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION(
|
|
DBG_MSG_TRACE_BEGIN;
|
|
);
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
// Do some stuff
|
|
if(MathRand() == 5)
|
|
{ DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN(5); }
|
|
|
|
// Return
|
|
DBG_TRACE_EXPERT_MAIN_CALL_SUB_FUNCTION_RETURN((int)NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enable tracing of this function
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Example function with return value |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function debug trace code
|
|
#ifdef DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION
|
|
#undef DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION(x) x
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION_RETURN(x) DBG_MSG_TRACE_RETURN_VAR((int)x)
|
|
|
|
#else
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION(x)
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x)
|
|
|
|
#endif
|
|
/////////////////////////////////////
|
|
const int call_sub2_function()
|
|
{
|
|
DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION(
|
|
DBG_MSG_TRACE_BEGIN;
|
|
);
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
// Do some stuff
|
|
if(MathRand() == 12)
|
|
{ DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION_RETURN(12); }
|
|
|
|
// Return
|
|
DBG_TRACE_EXPERT_MAIN_CALL_SUB2_FUNCTION_RETURN(NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CObj
|
|
{
|
|
public:
|
|
int test;
|
|
|
|
CObj() :
|
|
test(NULL)
|
|
{ };
|
|
|
|
CObj(const CObj& p_in)
|
|
{
|
|
test = p_in.test;
|
|
printf("%s", "COPY");
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
// Enable tracing of this function
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Example function with return object |
|
|
//+------------------------------------------------------------------+
|
|
/////////////////////////////////////
|
|
// Function debug trace code
|
|
#ifdef DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION
|
|
#undef DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION(x) x
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x)
|
|
|
|
#else
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION(x)
|
|
#define DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x)
|
|
|
|
#endif
|
|
/////////////////////////////////////
|
|
CObj call_obj_function()
|
|
{
|
|
DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION(
|
|
DBG_MSG_TRACE_BEGIN;
|
|
);
|
|
PERF_COUNTER_BEGIN;
|
|
|
|
// Local init
|
|
CObj test_obj;
|
|
CObj* test_ptr = new CObj();
|
|
|
|
Print("1");
|
|
|
|
//DBG_TO_STRING(PERF_COUNTER_TIMEIT_O(test_obj));
|
|
|
|
CObj retval = PERF_COUNTER_TIMEIT_O(test_obj);
|
|
|
|
Print("2");
|
|
CObj* ret_ptr1 = PERF_COUNTER_TIMEIT_O(test_ptr);
|
|
|
|
Print("3");
|
|
CObj* ret_ptr2 = PERF_COUNTER_TIMEIT_R(test_ptr);
|
|
|
|
Print("4");
|
|
|
|
|
|
// Output arrays
|
|
int i_arr[50];
|
|
for(int cnt = NULL; (cnt < 50) && !_StopFlag; cnt++)
|
|
{ i_arr[cnt] = MathRand(); }
|
|
DBG_MSG_VAR(i_arr);
|
|
|
|
DBG_MSG_VAR(1);
|
|
DBG_MSG_VAR(test_obj);
|
|
DBG_MSG_VAR(test_ptr);
|
|
|
|
// Do some stuff
|
|
if(MathRand() == 12)
|
|
{ DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION_RETURN(test_obj); }
|
|
|
|
// Return
|
|
DBG_TRACE_EXPERT_MAIN_CALL_OBJ_FUNCTION_RETURN(test_obj);
|
|
}
|
|
|
|
|