Let’s consider how critical sections are implemented in expert advisors.
The point is that if at the moment when these functions are executing arrays of data stored in global variables are concurrently accessed from several expert advisors the result will be unpredictable and in most cases the data will be spoiled.
In order to prevent this we will create an object “critical section” that can be in two states:
- «green light» (-1); и
- «red light» (1).
At each specified moment only one expert advisor can access the data. «Red light» means that this expert advisor is receiving the data and other expert advisors have to wait for the «green light». «Green light», means the road is free as nobody addresses the data at the moment.
We’ll write two functions:
- Lock() — we call it before we begin to work with a resource. The function waits for the «green light» and changes it for the «red light».
- Unlock() — we call it necessarily after we complete working with a resource in order to give the «green light».
Here is the source code of these functions :
//+------------------------------------------------------------------+
//| Lock() |
//| |
//| Returns: |
//| 0 – if "critical section" has been locked |
//| successfully |
//| 1 – in case of an error |
//| 2 – the expert advisor has been stopped |
//| 3 – in case of timeout (waited for too long) |
//+------------------------------------------------------------------+
int Lock(string GlobVarName, int timeout = 0)
{
string critical_section = GlobVarName+"Lock";
// we’ll check whether variable critical_section exisits
if (!GlobalVariableCheck(critical_section))
{
if (GetLastError()!=0) return(1);
// the variable doesn’t exist, we’ll create it
if (GlobalVariableSet(critical_section, -1.0)==0) return(1);
// the variable has been created
}
int StartTime = GetTickCount();
// waiting for the "green light"
while (true)
{
// we’ll check if the "green light" is on
if (GlobalVariableGet(critical_section)==-1.0)
{
// the "green light " has turned on, we turn on the "red light"
if (GlobalVariableSetOnCondition(critical_section, 1.0, -1.0)) return(0);
// we were surpassed, that’s why we wait for the "green light"
}
// we’ll check of the expert advisor hasn’t been stopped
if (IsStopped()) return(2);
// isn’t time out up?
if (timeout!=0)
{
if ((GetTickCount()-StartTime)>timeout*1000) return(3);
}
// we sleep for 0.1 second
Sleep(100);
}
}
//+------------------------------------------------------------------+
//| Unlock() |
//| |
//| Returns: |
//| 0 - if "critical section" is unlocked |
//| successfully |
//| 1 – in case of an error |
//| 2 – expert advisor has been stopped |
//| 3 – by timeout (waited for too long) |
//+------------------------------------------------------------------+
int Unlock(string GlobVarName, int timeout = 0)
{
string critical_section = GlobVarName+"Lock";
// we’ll check if variable critical_section exisits
if (!GlobalVariableCheck(critical_section))
{
if (GetLastError()!=0) return(1);
// the variable doesn’t exisit, we’ll create it
if (GlobalVariableSet(critical_section, -1.0)==0) return(1);
// the variable is created that’s why we exit
return(-1.0);
}
int StartTime = GetTickCount();
// infinite cycle
while (true)
{
// we try to set the "green light"
if (GlobalVariableSetOnCondition(critical_section, -1.0, 1.0)) return(0);
// we’ll check if the expert advisor hasn’t been stopped
if (IsStopped()) return(2);
// isn’t the timeout up?
if (timeout!=0)
{
if ((GetTickCount()-StartTime)>timeout*1000) return(3);
}
// we sleep for 0.1 second
Sleep(100);
}
}
Next article: "
OrderLots() Function"