#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "Pour tester le fonctionnement de la fonction GlobalVariableSetOnCondition,"
#property description "il est nécessaire d'exécuter l'EA sur plusieurs graphiques simultanément."
#define EXP_NAME StringSubstr(__FILE__, 0, StringLen(__FILE__)-4) // program name
#define MUTEX EXP_NAME+"_MUTEX" // nom de la variable globale mutex
#define DELAY 5000 // nombre de millisecondes d'émulation de l'EA
input long InpExpMagic = 0; /* Expert magic number */ // Id de l'EA. Si 0, l'id du graphique est utilisé
union LongDouble // union pour écrire et récupérer des valeurs longues à partir de double
{
long lvalue; // valeur de type long
double dvalue; // valeur de type double
};
//--- variables globales de l'EA
long ExtExpMagic; // Id de l'EA
ulong ExtStart; // moment du démarrage des calculs de l'EA
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- attribue l'ID du graphique à l'ID de l'EA si une valeur nulle est spécifiée
ExtExpMagic=(InpExpMagic==0 ? ChartID() : InpExpMagic);
//--- crée un mutex, s'il y a une erreur, renvoie une erreur d'initialisation
if(!MutexCreate())
return(INIT_FAILED);
//--- initialisation réussie
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- si le mutex est capturé par l'EA, relâche le mutex
if(MutexGetExpertID()==ExtExpMagic)
MutexRelease();
//--- nettoyage
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//-- crée le mutex s'il n'existe pas. S'il y a une erreur, on passe au tick suivant
if(!GlobalVariableCheck(MUTEX) && !MutexCreate())
return;
//--- récupère l'ID d'expert défini dans la variable globale du terminal
long magic=MutexGetExpertID();
//--- si l'ID appartient à l'EA, simule son travail
if(magic==ExtExpMagic)
{
//--- si le "travail" EA est terminé, libére le mutex
if(EAProgressHandler(ExtStart))
MutexRelease();
return;
}
//--- mutex capturé par un autre EA
else
{
//--- si le mutex est déjà relâché
if(magic==0)
{
//--- occupe le mutex et mémorise l'heure d'accès au travail
if(MutexOccupy())
{
PrintFormat("%s: Mutex is occupied by %s",Symbol(), ExpertIDDescription());
ExtStart=GetTickCount64();
}
return;
}
//--- mutex toujours occupé par un autre EA - travaux interdits
else
return;
}
/*
résultat de l'exécution de deux EA identiques sur les graphiques EURUSD et 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
nous pouvons voir que le premier EA à occuper le mutex est celui dans lequel le tick est arrivé en premier
après l'achèvement du cycle de travail, si le tick est revenu en premier ici,
le même EA occupe à nouveau le mutex
*/
}
//+------------------------------------------------------------------+
//| Émulateur de gestionnaire d'opérations de l'EA |
//+------------------------------------------------------------------+
bool EAProgressHandler(ulong start)
{
//--- si l'heure spécifiée s'est écoulée depuis que le handler a commencé à travailler
if(GetTickCount64()-start>=DELAY)
{
//--- rapporte au journal l'achèvement du handler,
//--- définit une nouvelle heure de début pour le handler et renvoie 'true'
PrintFormat("%s: %s end", Symbol(), ExpertIDDescription());
start=GetTickCount64();
return(true);
}
//--- le temps de fonctionnement de l'émulateur de calcul de l'EA n'est pas encore terminé -
//--- rapporte le prochain tick dans le journal
else
{
PrintFormat("%s: %s next tick", Symbol(), ExpertIDDescription());
}
//--- le temps de travail n'est pas encore terminé - renvoie 'false'
return(false);
}
//+------------------------------------------------------------------+
//| Crée un mutex et le définit sur l'état verrouillé |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Capture le mutex |
//+------------------------------------------------------------------+
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;
s ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, magic.dvalue, 0))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Relâche le mutex |
//+------------------------------------------------------------------+
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;
s ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, 0, magic.dvalue))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Retourne la valeur du mutex |
//+------------------------------------------------------------------+
long MutexGetExpertID(void)
{
LongDouble magic={};
s ResetLastError();
if(!GlobalVariableGet(MUTEX, magic.dvalue))
{
PrintFormat("%s: GlobalVariableGet() failed. Error %d",__FUNCTION__, GetLastError());
return(WRONG_VALUE);
}
return(magic.lvalue);
}
//+------------------------------------------------------------------+
//| Renvoie l'identifiant de l'EA sous forme de chaîne |
//+------------------------------------------------------------------+
string ExpertIDDescription(void)
{
return("Expert "+(string)ExtExpMagic);
}
|