GlobalVariableSetOnCondition

Establece un nuevo valor de una variable global existente, si el valor actual de la variable es igual al valor del tercer parámetro check_value. Si la variable no existe, la función generará el error ERR_GLOBALVARIABLE_NOT_FOUND (4501) y devolverá false.

bool  GlobalVariableSetOnCondition(
   string  name,            // nombre
   double  value,           // valor si se cumple la condición
   double  check_value      // condición que se comprueba
   );

Parámetros

name

[in]  Nombre de la variable global.

value

[in] Valor nuevo.

check_value

[in]   Valor para comprobar el valor actual de la variable global.

Valor devuelto

En caso de éxito la función devuelve true, de lo contrario devuelve false. Para obtener la información sobre el error, hay que llamar a la función GetLastError(). Si el valor actual de la variable global es diferente a check_value, la función devolverá false.

Nota

La función proporciona el acceso atómico a una variable global, por eso se puede usarla para organizar un mutex en caso de interacción de varios Asesores Expertos que trabajan al mismo tiempo dentro de un terminal de cliente.

 

Ejemplo:

#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__0StringLen(__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:
   EURUSDMutex is occupied by Expert 133829812107724569
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 end
   EURUSDMutex is occupied by Expert 133829812107724569
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 end
   AUDUSDMutex is occupied by Expert 128968168951083984
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 end
   AUDUSDMutex is occupied by Expert 128968168951083984
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 end
   EURUSDMutex is occupied by Expert 133829812107724569
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 end
   EURUSDMutex is occupied by Expert 133829812107724569
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 end
   AUDUSDMutex is occupied by Expert 128968168951083984
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 next tick
   AUDUSDExpert 128968168951083984 end
   EURUSDMutex is occupied by Expert 133829812107724569
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 133829812107724569 next tick
   EURUSDExpert 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(MUTEXmagic.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(MUTEXmagic.dvalue0))
     {
      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(MUTEX0magic.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(MUTEXmagic.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);
  }