#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "To test the functionality of the GlobalVariableSetOnCondition function,"
#property description "it is necessary to run the EA on several charts simultaneously."
#define EXP_NAME StringSubstr(__FILE__, 0, StringLen(__FILE__)-4) // Programmname
#define MUTEX EXP_NAME+"_MUTEX" // Mutex-Name der globalen Variablen
#define DELAY 5000 // Anzahl der Millisekunden der EA-Emulation
input long InpExpMagic = 0; /* Expert magic number */ // EA ID. Ist sie 0, wird die ID des Charts verwendet
union LongDouble // Verbindung zum Schreiben und Abrufen 'long'-Werte aus einem 'double'-Wert
{
long lvalue; // 'long'-Wert
double dvalue; // 'double'-Wert
};
//--- globale Variablen des EAs
long ExtExpMagic; // EA ID
ulong ExtStart; // Moment, zu dem der EA zu rechnen beginnt
//+------------------------------------------------------------------+
//| Expert Initialisierungsfunktion |
//+------------------------------------------------------------------+
int OnInit()
{
//--- der EA-ID die Chart-ID zuweisen, wenn der Wert Null ist.
ExtExpMagic=(InpExpMagic==0 ? ChartID() : InpExpMagic);
//--- Mutex erstellen, bei einem Fehler einen Initialisierungsfehler zurückgeben
if(!MutexCreate())
return(INIT_FAILED);
//--- erfolgreiche Initialisierung
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Deinitialisierungsfunktion des Experten |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Wenn Mutex vom EA erfasst wird, Mutex freigeben
if(MutexGetExpertID()==ExtExpMagic)
MutexRelease();
//--- aufräumen
Comment("");
}
//+------------------------------------------------------------------+
//| Tick-Funktion des Experten |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Wenn nicht vorhanden ist, wird Mutex erstellt; wenn ein Fehler auftritt, warte bis zum nächsten Tick.
if(!GlobalVariableCheck(MUTEX) && !MutexCreate())
return;
//--- die in der globalen Variable des Terminals festgelegte ID des Experten abrufen
long magic=MutexGetExpertID();
//--- wenn die ID zum EA gehört, simuliere dessen Arbeit
if(magic==ExtExpMagic)
{
//--- wenn die „Arbeit” des EAs abgeschlossen ist, Mutex freigeben
if(EAProgressHandler(ExtStart))
MutexRelease();
return;
}
//--- Mutex von einem anderen EA erfasst
else
{
//--- wenn Mutex bereits freigegeben ist
if(magic==0)
{
//--- Mutex belegen und Zugriffszeit speichern
if(MutexOccupy())
{
PrintFormat("%s: Mutex is occupied by %s",Symbol(), ExpertIDDescription());
ExtStart=GetTickCount64();
}
return;
}
//--- Mutex wird noch von einem anderen EA belegt – Arbeit ist gesperrt
else
return;
}
/*
Ergebnis der Ausführung zweier identischer EAs auf den Charts EURUSD und AUDUSD:
EURUSD: Mutex is occupied by Expert 133829812107724569
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 end
EURUSD: Mutex is occupied by Expert 133829812107724569
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 end
AUDUSD: Mutex is occupied by Expert 128968168951083984
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 end
AUDUSD: Mutex is occupied by Expert 128968168951083984
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 end
EURUSD: Mutex is occupied by Expert 133829812107724569
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 end
EURUSD: Mutex is occupied by Expert 133829812107724569
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 end
AUDUSD: Mutex is occupied by Expert 128968168951083984
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 next tick
AUDUSD: Expert 128968168951083984 end
EURUSD: Mutex is occupied by Expert 133829812107724569
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 next tick
EURUSD: Expert 133829812107724569 end
Wir können sehen, dass der erste EA, der den Mutex belegt, derjenige ist, bei dem der Tick zuerst angekommen ist.
nach Abschluss des Arbeitszyklus sperrt derselbe EA den Mutex erneut, wenn der Tick auch hier zuerst angekommen ist.
*/
}
//+------------------------------------------------------------------+
//| EA-Operationshandler-Emulator |
//+------------------------------------------------------------------+
bool EAProgressHandler(ulong start)
{
//--- wenn die angegebene Zeit seit Beginn der Handler-Ausführung verstrichen ist
if(GetTickCount64()-start>=DELAY)
{
//--- Meldung an das Journal über die Fertigstellung des Handlers,
//--- neue Startzeit für den Handler festlegen und „true” zurückgeben
PrintFormat("%s: %s end", Symbol(), ExpertIDDescription());
start=GetTickCount64();
return(true);
}
//--- Die Betriebszeit des EA-Berechnungsemulators ist noch nicht abgeschlossen -
//--- Den nächsten Tick im Journal melden
else
{
PrintFormat("%s: %s next tick", Symbol(), ExpertIDDescription());
}
//--- Arbeitszeit ist noch nicht beendet – „false” zurückgeben
return(false);
}
//+------------------------------------------------------------------+
//| Mutex erstellen und in den gesperrten Zustand versetzen |
//+------------------------------------------------------------------+
bool MutexCreate(void)
{
if(!GlobalVariableCheck(MUTEX))
{
LongDouble magic={};
magic.lvalue=ExtExpMagic;
ResetLastError();
if(!GlobalVariableSet(MUTEX, magic.dvalue))
{
PrintFormat("%s: GlobalVariableSet() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
}
return(true);
}
//+------------------------------------------------------------------+
//| Mutex erfassen |
//+------------------------------------------------------------------+
bool MutexOccupy(void)
{
if(!GlobalVariableCheck(MUTEX))
{
PrintFormat("%s: Error! Mutex is missing. First create it with MutexCreate()",__FUNCTION__);
return(false);
}
LongDouble magic={};
magic.lvalue=ExtExpMagic;
ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, magic.dvalue, 0))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Mutex freigeben |
//+------------------------------------------------------------------+
bool MutexRelease(void)
{
if(!GlobalVariableCheck(MUTEX))
{
PrintFormat("%s: Error! Mutex is missing. First create it with MutexCreate()",__FUNCTION__);
return(false);
}
LongDouble magic={};
magic.lvalue=ExtExpMagic;
ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, 0, magic.dvalue))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Mutex-Wert zurückgeben |
//+------------------------------------------------------------------+
long MutexGetExpertID(void)
{
LongDouble magic={};
ResetLastError();
if(!GlobalVariableGet(MUTEX, magic.dvalue))
{
PrintFormat("%s: GlobalVariableGet() failed. Error %d",__FUNCTION__, GetLastError());
return(WRONG_VALUE);
}
return(magic.lvalue);
}
//+------------------------------------------------------------------+
//| EA-ID als Zeichenfolge zurückgeben |
//+------------------------------------------------------------------+
string ExpertIDDescription(void)
{
return("Expert "+(string)ExtExpMagic);
}
|