В данной статье будет рассказано о способе организации "критической секции" в советнике.
Дело в том, что если в момент выполнения этих функций будет осуществлен доступ к массивам данных, хранимых в глобальных переменных, из нескольких советников одновременно, то результат будет непредсказуемым и в большинстве случаев данные будут испорчены.
Для того, чтобы избежать этого, мы создадим объект "критическая секция", который может находиться в двух состояниях:
В каждый конкретный момент только один советник может получить доступ к данным. Пока советник получает данные, будет гореть "красный свет" и другие советники будут ждать "зеленового света". Если горит "зеленый свет", то дорога свободна, т. к. никто в данный момент к данным не обращается.
Напишем две функции:
Вот исходный код этих функций:
// 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); } }
В следующей статье разберем код этих функций подробней.
Есть что сказать? Не стесняйтесь!
Последние статьи:
Видео по теме:
УГОЛОК АДМИНИСТРАТОРА