Расскажем оспособе организации критической секции всоветнике.
Дело втом, что если вмомент выполнения этих функций будет осуществлен доступ кмассивам данных, хранимых вглобальных переменных, изнескольких советников одновременно, торезультат будет непредсказуемым ивбольшинстве случаев данные будут испорчены.
Для того, чтобы избежать этого, мысоздадим объект критическая секция, который может находиться вдвух состояниях:
- зеленый свет (-1); и
- красный свет (1).
В каждый конкретный момент только один советник может получить доступ кданным. Пока советник получает данные, будет гореть красный свет идругие советники будут ждать зеленового света. Если горит зеленый свет, тодорога свободна, т.к. никто вданный момент кданным необращается.
Напишем две функции:
- Lock() вызываем ееперед началом работы сресурсом. Функция ждет зеленового света именяет его накрасный.
- Unlock() обязательно вызываем еепосле окончания работы сресурсом, чтобы снова зажечь зеленый свет.
Вот исходный код этих функций:
//+------------------------------------------------------------------+
//| Lock() |
//| |
//| Возвращает: |
//| 0 - если "критическая секция" успешно |
//| заблокирована |
//| 1 - в случае ошибки |
//| 2 - эксперт остановлен |
//| 3 - по таймауту (слишком долго ждали) |
//+------------------------------------------------------------------+
int Lock(string GlobVarName, int timeout = 0)
{
string critical_section = GlobVarName+"Lock";
// проверим, существует ли переменная critical_section
if (!GlobalVariableCheck(critical_section))
{
if (GetLastError()!=0) return(1);
// переменная не существует, создадим ее
if (GlobalVariableSet(critical_section, -1.0)==0) return(1);
// переменная создана
}
int StartTime = GetTickCount();
// ждем "зеленового света"
while (true)
{
// проверить, не загорелся ли "зеленый свет"
if (GlobalVariableGet(critical_section)==-1.0)
{
// "зеленый свет" загорелся, зажигаем "красный свет"
if (GlobalVariableSetOnCondition(critical_section, 1.0, -1.0)) return(0);
// нас опередили, поэтому ждем "зеленового света"
}
// проверим, не остановлен ли эксперт
if (IsStopped()) return(2);
// таймаут не истек?
if (timeout!=0)
{
if ((GetTickCount()-StartTime)>timeout*1000) return(3);
}
// спим 0.1 секунды
Sleep(100);
}
}
//+------------------------------------------------------------------+
//| Unlock() |
//| |
//| Возвращает: |
//| 0 - если "критическая секция" успешно |
//| разблокирована |
//| 1 - в случае ошибки |
//| 2 - эксперт остановлен |
//| 3 - по таймауту (слишком долго ждали) |
//+------------------------------------------------------------------+
int Unlock(string GlobVarName, int timeout = 0)
{
string critical_section = GlobVarName+"Lock";
// проверим, существует ли переменная critical_section
if (!GlobalVariableCheck(critical_section))
{
if (GetLastError()!=0) return(1);
// переменная не существует, создадим ее
if (GlobalVariableSet(critical_section, -1.0)==0) return(1);
// переменная создана, поэтому выходим
return(-1.0);
}
int StartTime = GetTickCount();
// бесконечный цикл
while (true)
{
// пытаемся установить "зеленый свет"
if (GlobalVariableSetOnCondition(critical_section, -1.0, 1.0)) return(0);
// проверим, не остановлен ли эксперт
if (IsStopped()) return(2);
// таймаут не истек?
if (timeout!=0)
{
if ((GetTickCount()-StartTime)>timeout*1000) return(3);
}
// спим 0.1 секунды
Sleep(100);
}
}
Перейти к главе «
функция OrderLots()».