#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "Per testare la funzionalità della funzione GlobalVariableSetOnCondition,"
#property description "è necessario eseguire l'EA su più grafici contemporaneamente."
#define EXP_NAME StringSubstr(__FILE__, 0, StringLen(__FILE__)-4) // program name
#define MUTEX EXP_NAME+"_MUTEX" // nome della variabile globale mutex
#define DELAY 5000 // numero di millisecondi di emulazione EA
input long InpExpMagic = 0; /* Expert magic number */ // ID dell'EA. Se 0, viene utilizzato l'ID del grafico
union LongDouble // unione per scrivere e recuperare valori long da double
{
long lvalue; // valore long
double dvalue; // valore double
};
//--- Variabili globali dell'EA
long ExtExpMagic; // ID dell'EA
ulong ExtStart; // momento in cui iniziano i "calcoli" dell'EA
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- assegnare l'ID del grafico all'ID dell'EA se viene specificato un valore zero
ExtExpMagic=(InpExpMagic==0 ? ChartID() : InpExpMagic);
//--- creare mutex, se c'è un errore, restituire un errore di inizializzazione
if(!MutexCreate())
return(INIT_FAILED);
//--- inizializzazione avvenuta con successo
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- se mutex viene catturato dall'EA, rilasciare mutex
if(MutexGetExpertID()==ExtExpMagic)
MutexRelease();
//--- ripulire
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- se non c'è mutex, crearlo; se c'è un errore, lasciare fino al tick successivo
if(!GlobalVariableCheck(MUTEX) && !MutexCreate())
return;
//--- ottenere l'ID dell'expert impostato nella variabile globale del terminale
long magic=MutexGetExpertID();
//--- se l'ID appartiene all'EA, simula il suo lavoro
if(magic==ExtExpMagic)
{
//--- se il "lavoro" dell'EA è completato, rilasciare mutex
if(EAProgressHandler(ExtStart))
MutexRelease();
return;
}
//--- mutex catturato da un altro EA
else
{
//--- se mutex è già stato rilasciato
if(magic==0)
{
//--- occupa mutex e ricorda l'ora di accesso al lavoro
if(MutexOccupy())
{
PrintFormat("%s: Mutex is occupied by %s",Symbol(), ExpertIDDescription());
ExtStart=GetTickCount64();
}
return;
}
//--- mutex ancora occupato da un altro EA - il lavoro è vietato
else
return;
}
/*
risultato dell'esecuzione di due EA identici sui grafici EURUSD e 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
possiamo vedere che il primo EA ad occupare il mutex è quello in cui il tick è arrivato per primo
dopo il completamento del ciclo di lavoro, se il tick torna prima qui,
lo stesso EA occupa di nuovo il mutex
*/
}
//+------------------------------------------------------------------+
//| Emulatore del gestore delle operazioni dell'EA |
//+------------------------------------------------------------------+
bool EAProgressHandler(ulong start)
{
//--- se è trascorso il tempo specificato da quando il gestore ha iniziato a funzionare
if(GetTickCount64()-start>=DELAY)
{
//--- riportare nel journal in merito al completamento del gestore,
//--- impostare un nuovo orario di inizio per il gestore e restituire 'true
PrintFormat("%s: %s end", Symbol(), ExpertIDDescription());
start=GetTickCount64();
return(true);
}
//--- il tempo di funzionamento dell'emulatore di calcolo dell'EA non è stato ancora completato -
//--- riportare il prossimo tick nel journal
else
{
PrintFormat("%s: %s next tick", Symbol(), ExpertIDDescription());
}
//--- l'orario di lavoro non è ancora terminato - restituisci 'false'
return(false);
}
//+------------------------------------------------------------------+
//| Creare mutex, impostarlo sullo stato bloccato |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Catturare 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;
ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, magic.dvalue, 0))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Rilasciare 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;
ResetLastError();
if(!GlobalVariableSetOnCondition(MUTEX, 0, magic.dvalue))
{
PrintFormat("%s: GlobalVariableSetOnCondition() failed. Error %d",__FUNCTION__, GetLastError());
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| Restituire il valore di mutex |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Restituire ID dell'EA come stringa |
//+------------------------------------------------------------------+
string ExpertIDDescription(void)
{
return("Expert "+(string)ExtExpMagic);
}
|