#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "Para comprobar la funcionalidad de la función GlobalVariableSetOnCondition"
#property description "es necesario ejecutar este experto en varios gráficos simultáneamente."
#define EXP_NAME StringSubstr(__FILE__, 0, StringLen(__FILE__)-4) // nombre del programa
#define MUTEX EXP_NAME+"_MUTEX" // nombre de la variable mutex global
#define DELAY 5000 // número de milisegundos de emulación del funcionamiento del experto
input long InpExpMagic = 0; /* Expert magic number */ // identificador del experto. Si el valor es 0, se utiliza el identificador del gráfico
union LongDouble // unión para escribir y recuperar valores long de double
{
long lvalue; // long value
double dvalue; // double value
};
//--- variables globales del asesor
long ExtExpMagic; // identificador del experto
ulong ExtStart; // momento de inicio de los "cálculos" del asesor
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- asignamos el identificador del gráfico al identificador del experto si se especifica un valor cero
ExtExpMagic=(InpExpMagic==0 ? ChartID() : InpExpMagic);
//--- creamos un mutex y retornamos el error de inicialización si ocurre un error
if(!MutexCreate())
return(INIT_FAILED);
//--- la inicialización ha tenido éxito
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- si este asesor captura el mutex, liberamos el mutex
if(MutexGetExpertID()==ExtExpMagic)
MutexRelease();
//--- ponemos orden
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- si no hay mutex, lo creamos; si hay un error, lo dejamos hasta el siguiente tick
if(!GlobalVariableCheck(MUTEX) && !MutexCreate())
return;
//--- obtenemos el ID del experto registrado en la variable global del terminal
long magic=MutexGetExpertID();
//--- si el identificador pertenece a este experto, simulamos su funcionamiento
if(magic==ExtExpMagic)
{
//--- si el "funcionamiento" del experto ha finalizado, liberamos el mutex
if(EAProgressHandler(ExtStart))
MutexRelease();
return;
}
//--- el mutex ha sido capturado por otro asesor
else
{
//--- si el mutex ya ha sido liberado
if(magic==0)
{
//--- ocupamos el mutex y recordamos la hora de acceso al funcionamiento
if(MutexOccupy())
{
PrintFormat("%s: Mutex is occupied by %s",Symbol(), ExpertIDDescription());
ExtStart=GetTickCount64();
}
return;
}
//--- el mutex sigue ocupado con otro asesor, el trabajo queda prohibido
else
return;
}
/*
resultado de la ejecución de dos asesores idénticos en los gráficos EURUSD y 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
se ve que el primer mutex lo ocupa el asesor donde el tick ha llegado primero
una vez finalizado el ciclo de trabajo, si el tick ha llegado primero de nuevo al mismo lugar,
este mismo asesor volverá a ocupar el mutex
*/
}
//+------------------------------------------------------------------+
//| Manejador-emulador del funcionamiento del asesor |
//+------------------------------------------------------------------+
bool EAProgressHandler(ulong start)
{
//--- si ha transcurrido un tiempo específico desde que el manejador ha comenzado a funcionar
if(GetTickCount64()-start>=DELAY)
{
//--- informamos al registro de la finalización del funcionamiento del manejador,
//--- establecemos una nueva hora de inicio para el manejador y retornamos true
PrintFormat("%s: %s end", Symbol(), ExpertIDDescription());
start=GetTickCount64();
return(true);
}
//--- el tiempo de ejecución del emulador de cálculo del asesor aún no se ha completado -
//--- informamos al registro sobre el nuevo tick
else
{
PrintFormat("%s: %s next tick", Symbol(), ExpertIDDescription());
}
//--- el tiempo de trabajo aún no se ha completado, retornamos false
return(false);
}
//+------------------------------------------------------------------+
//| Crea un mutex y lo establece en un estado bloqueado |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| Captura el 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);
}
//+------------------------------------------------------------------+
//| Libera el 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);
}
//+------------------------------------------------------------------+
//| Retorna el valor del 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);
}
//+------------------------------------------------------------------+
//| Retorna en forma de línea el identificador del asesor |
//+------------------------------------------------------------------+
string ExpertIDDescription(void)
{
return("Expert "+(string)ExtExpMagic);
}
|