Features of the mql5 language, subtleties and tricks - page 188

 
Nikolai Semko:
The question is how you can start a non-static class method by a pointer even if the object of other class (in this case CTimer) is a property (variable) of the class.

no.... of course you can pass a pointer to another object and change the pointer there to call method.... but you need to know the name of the method.

ZS: but wrote yesterday, use an example@fxsaber and inherit, in each class will be called by OnTimer , there will only be a base class in the loop to check which timer has what timer interval, and the launch of the main timer in static method implement

 
Nikolai Semko:
The question is how you can use a pointer to run a non-static method of a class even if the object of another class (in this case CTimer) is a property (variable) of that class. Is it possible? I'm afraid not.

- templates

- interfaces

 

templates:

template <typename C> class Timer
{
public:
  Timer(C* c)
  : p(c)
  {}

  void OnTimer()
  {
    p->OnTimer();
  }
private:
  C* p;
}

class Handler
{
public:
  Handler()
  : t(this)
  {}

  void OnTimer() {}
private:
  Timer<Handler> t;
}

No implementation of the timer itself here, just an example of how to call a non-static function (wrote directly in the forum, didn't check)

 

Forum on trading, automated trading systems and trading strategy testing

MT5 and Speed in Action

fxsaber, 2020.10.04 11:56

Determines if a program is running on a braked machine or not.

// Возвращает true, если тормозной VPS.
bool IsFreezeVPS()
{
  static bool FirstRun = true;
  static bool Res;
  
  if (FirstRun)
  {
    if (Res = ::GetMicrosecondCount() - ::GetMicrosecondCount())
      ::Alert("Warning: FreezeVPS - https://www.mql5.com/ru/forum/342090/page40#comment_18579094");
    
    FirstRun = false;
  }
  
  return(Res);
}
 
Nikolai Semko:
The question is how to run a non-static class method by pointer even if the object of another class (in this case CTimer) is a property (variable) of this class. And is it possible? I'm afraid not.

In general terms, it looks like this:

#define  USING_STD

#include <STD\Time\Timer.mqh>

class CTest{
   _tTimerEvent<CTest> cEvent;
public:
   CTest(_tTimer* mTimer):cEvent(&this,mTimer){}
   void TimerEvent(_tTimerInfo &info){
      PrintFormat("Timer check in class at %llu, current delta %llu, count from last %u",info.lastTimer,info.delta,info.count);
   }
};

_tTimer gTimer1;
_tTimer gTimer2;

CTest gTest(&gTimer1);

int OnInit(void)
  {
   EventSetMillisecondTimer(20);
   ulong timer=GetMicrosecondCount();
   if (!gTimer1) gTimer1.Reset(timer,1000000); //1 s
   if (!gTimer2) gTimer2.Reset(timer,2000000).Function(TimerEvent); //2 s
   TimerControl(timer);
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason){
   TimerControl(GetMicrosecondCount());
// или gTimer.Free();
   EventKillTimer();
  }

void OnTick()
   {
   TimerControl(GetMicrosecondCount());
  }
  
void OnTimer(void)
  {
   TimerControl(GetMicrosecondCount());
  }
//+------------------------------------------------------------------+
void TimerControl(ulong fTimer){
   gTimer1.Control(fTimer);
   gTimer2.Control(fTimer);
}

void TimerEvent(_tTimerInfo &info){
   PrintFormat("Timer check in function %llu, current delta %llu, count from last %u",info.lastTimer,info.delta,info.count);
}

You can download the lib from here: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent branch, not yet merged into the master.

 
Igor Makanu:

no.... of course you can pass a pointer to another object and change the pointer there to call method.... but you need to know the name of the method.

ZS: but wrote yesterday, use an example@fxsaber and inherit, in each class will be called by OnTimer, it will only remain in the base class in the loop to check which timer has what timer interval, and the launch of the main timer in static method implement

Igor, I don't understand what fxsaber code we're talking about

Andrei Trukhanovich:

templates:

There's no implementation of the timer itself, only an example of how to call a non-static function (wrote directly on the forum, didn't check)

Thank you. Tried it. Nothing comes out.

Vladimir Simakov:

In general, it looks like this:

You download the library from here: https://github.com/sva04091979/STD/tree/TimerEvent. TimerEvent branch, I haven't merged it into the master yet.

Thank you. But I haven't found how to run a non-static class method by the pointer either.


Thanks to all of you, but maybe I haven't worded the task correctly or haven't found a solution in your article due to my limited knowledge.
What do you need?
Here is an example of an indicator.
The method Timer4 (marked blue) of CTestTimer class is launched by the pointer from CTimer class (in the loop of CTimer:: OnTimer method) passed to CTimer::NewTimer class at the moment of constructor execution when the object of CTestTimer class is created.
I tried everything. There is a deadlock. There is no way to get a pointer to this method. In C++ it works through: typedef void (CTestTimer::*TFun)();
And there is a strange error: 'Timer4' - pointer to this function type is not supported yet ('Timer4' - pointer to this function type is not supported yet)
"For now" - as if MQ put this question aside till better times.

#property indicator_chart_window
#include <Timer.mqh> // https://www.mql5.com/ru/code/31306

//+------------------------------------------------------------------+
class CTestTimer {
 private:
   //typedef void (CTestTimer::*TFunc2)(); // так работает в C++, но здесь не работает
 public:
   int x4;
   CTestTimer() {
      x4=0;
      //TFunc2 p=CTestTimer::Timer4;
      //TFunc2 p=Timer4;
      //timers.NewTimer(700,p);
      timers.NewTimer(700,CTestTimer::Timer4); // ошибка 'Timer4' - pointer to this function type is not supported yet
   };
   ~CTestTimer(){};
   void Timer4() {
      x4++;
      if (x4==7) timers.KillTimer(CTestTimer::Timer4); // удаляем этот таймер
   }
};
//+------------------------------------------------------------------+


int x1=0;
int x2=0;
int x3=0;
CTestTimer X= new CTestTimer;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit() {
   timers.NewTimer(500,  Timer1); // создаем новый таймер с периодом обновления 500   милисекунд и функцией-обраточником Timer1()
   timers.NewTimer(1000, Timer2); // создаем новый таймер с периодом обновления 1000  милисекунд и функцией-обраточником Timer2()
   timers.NewTimer(2000, Timer3); // создаем новый таймер с периодом обновления 2000  милисекунд и функцией-обраточником Timer3()
   timers.NewTimer(100,  Timer5); // создаем новый таймер с периодом обновления 100   милисекунд и функцией-обраточником Timer5()
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   Comment("");
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) {
   return(rates_total);
}
//+------------------------------------------------------------------+
void Timer1() {  // данная функция вызывается каждые 500 миллисекунд
   x1++;
   if (x1==50) timers.KillTimer(Timer1); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer2() {  // данная функция вызывается каждые 1000 миллисекунд
   x2++;
   if (x2==22) timers.KillTimer(Timer2); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer3() {  // данная функция вызывается каждые 2000 миллисекунд
   x3++;
   if (x3==10) timers.KillTimer(Timer3); // удаляем этот таймер
}
//+------------------------------------------------------------------+
void Timer5() {  // данная функция вызывается каждые 100 миллисекунд
   if (x1==50) timers.KillTimer(Timer5); // удаляем этот таймер
   Comment("x1=" +string(x1)+";\nx2="+string(x2)+";\nx3="+string(x3)+";\nx3="+string(X.x4)+"\nВсего таймеров - "+string(timers.GetN()));
}
//+------------------------------------------------------------------+
It seems that there is no solution to this problem in the current state of the MQL5 language
 
Nikolai Semko:

Igor, I do not understand which fxsaber code we are talking about

https://www.mql5.com/ru/forum/325418/page4#comment_16116740

the value of this code is.... well, you can create your own dynamic object anywhere in the code -.... and don't bother updating it, and it will be nailed down by itself when you exit the program

the number of such timers is limited only by your imagination... I wanted to move a sprite - created an object that crawled from the left edge of the screen to the right and killed itself - so to speak, complete autonomy

...too lazy to write an example, not an interesting task

 
Igor Makanu:

https://www.mql5.com/ru/forum/325418/page4#comment_16116740

the value of this code.... well, you can create your own dynamic object.... anywhere in the code and don't bother updating it and when you exit the program, it will be nailed down by itself

the number of such timers is limited only by your imagination... I wanted to move a sprite - created an object that crawled from the left edge of the screen to the right and killed itself - so to speak, complete autonomy

...too lazy to write an example, not an interesting task

Yeah, I took a quick look at it.
didn't get it

virtual void 0;
virtual void 0;
 
Nikolai Semko:

Yeah, I took a quick look at it.
didn't understand that point.

I don't know why the code looks like that now, but it should be:

 virtual void OnInit() =0;
 virtual void OnTick() =0;
 virtual void OnDeinit( const int )=0;

but you don't need these methods for the timer, imho.

ZS: the object can kill itself like this

delete &this;
 
Igor Makanu:

I don't know why the code looks like that, but it should be:

but you don't need these methods for the timer, imho.

ZS: The object can kill itself like this

Got it, thanks to you and @fxsaber. Saved it in my piggy bank.

But, of course, there is no answer to my question in this code.