июня 01 2010

Таймеры и время

При решении некоторых задач программа должна отслеживать текущее время или выполнять какие-либо действия с определенной периодичностью. Например, эта проблема возникает в приложениях, имитирующих аппаратуру, работающую в реальном масштабе времени, в игровых и мультимедийных приложениях, а также при проведении различных тестов. Кроме того, иногда требуется отладить критичные ко времени исполнения фрагменты кода, для чего нужен «хронометр» с высокой разрешающей способностью.
Win32 API содержит как функции для измерения текущего времени, так и функции для создания виртуальных таймеров — устройств, извещающих приложение об истечении заданного интервала времени. Для успешного применения этих программных средств необходимо учитывать их разрешающую способность и потенциальную точность измерения.
Важно понимать, что многозадачная операционная система Windows не является системой реального времени, поэтому любой виртуальный таймер в Windows не может гарантировать какой бы то ни было фактической точности отсчета временного интервала. Ведь в любой момент времени система может прервать выполнение вашего приложения, чтобы дать возможность поработать другому приложению (простой, вызванный прерыванием, чаще всего длится от 1 до 30 мс1). Вероятность таких прерываний тем ниже, чем меньше рассматриваемый временной интервал и чем меньше других программ работает одновременно с вашим приложением. В то же время, как показывают эксперименты, мультимедийный таймер Windows обеспечивает вполне приемлемую фактическую точность отсчета временных интервалов для многих задач.


мая 29 2010

Системное время

Системное время в Windows содержит информацию о текущих дате и времени и представляет собой так называемое UTC-время (Universal Time Coordinated). Время в формате UTC основывается на среднем времени по Гринвичу. Системное время может быть получено при помощи функции GetSystemTime:
VOID GetSystemTimeCLPSYSTEMTIME lpSystemTime);
Функция записывает результат в структуру типа SYSTEMTIME, адрес которой задается параметром lpSystemTime. Структура типа SYSTEMTIME содержит поля для года, месяца, дня недели, дня, часов, минут, секунд и миллисекунд.
Так как системное время отсчитывается по Гринвичу, то, скорее всего, оно не совпадает с местным временем, которое отображается на панели задач. Получить значение местного времени можно при помощи функции GelLocalTime, которая возвращает информацию в том же формате, что и функция GetSystemTime. Если вы считаете, что ваше приложение может изменять системное время, то это можно осуществить при помощи вызова функции SetSystemTime или SetLocalTime. В некоторых случаях может оказаться полезной пара функций, работающих с информацией о часовом поясе, — GetTimeZonelnformation и SetTimeZonelnformation.
Системное время считывается с часов реального времени, встроенных в компьютер и имеющих автономное питание, в момент запуска Windows. Затем операционная система обеспечивает приращения системного времени, используя прерывания системного таймера, аналогично управлению временем Windows. Таким образом, точность измерения времени с помощью GetSystemTime также определяется разрешением системного таймера.


мая 11 2010

Программирование задержек в исполнении кода

При создании реальных программ часто возникает необходимость «притормозить» исполнение кода в том или ином месте программы. В качестве простейшего примера можно привести игровую программу, перемещающую некий графический объект по экрану с помощью цикла while. Предположим, что вы отладили вашу программу на компьютере с процессором, имеющим тактовую частоту 500 МГц. Что произойдет, если эта программа будет исполняться на более мощном компьютере с тактовой частотой процессора 2 ГГц? Если не предусмотреть специальных мер, то объект будет двигаться гораздо быстрее, и не исключено, что играть станет совершенно невозможно. Типичное решение проблемы заключается в определении характеристик процессора и добавлении программируемых задержек в таких циклах. Другой пример, с которым мы столкнулись совсем недавно, —использование программируемой задержки для калибровки счетчика меток реального времени в классе KTimer.


Апр 28 2010

Мультимедийный таймер

Для использования в вашем приложении мультимедийного таймера необходимо подключить к проекту мультимедийную библиотеку winmm.lib1 и добавить в начало файла, в котором вызываются функции библиотеки, следующую директиву:
finclude
Содержащаяся в библиотеке функция timeGetDevCaps позволяет узнать поддерживаемое системой разрешение мультимедийного таймера. Для этого определите переменную структурного типа
TIMECAPS tc: и вызовите функцию
timeGetDevCaps(&tc, sizeof(TIMECAPS));
В результате этого вызова поля tc.wPeriodMin и tc.wPeriodMax будут содержать минимальное и максимальное разрешения в миллисекундах, поддерживаемые для мультимедийного таймера. Для нашего компьютера, например, были получены значения 1 мс и 1 000 000 мс соответственно.
Мультимедийная библиотека содержит функции timeBeginPeriod и timeEndPeriod, предназначенные для установки и отмены конкретного разрешения мультимедийного таймера. Величина разрешения в миллисекундах передается в виде параметра в обеих функциях.
MSDN рекомендует вызывать функцию timeBeginPeriod(tc.wPeriodMin) непосредственно перед тем, как обратиться к сервису мультимедийного таймера. Повышенное разрешение таймера, по-видимому, реализуется в системе при помощи создания отдельного потока с высоким приоритетом выполнения. Поэтому рекомендуется отменять режим повышенного разрешения таймера (timeEndPeriod), как только он перестает быть нужным.
Ранее мы уже использовали функции timeBeginPeriod и timeEndPeriod для повышения точности работы функции Sleep. Степень влияния этих функций на работу собственно мультимедийного таймера мы выясним, когда проведем эксперименты с тестовой программой.


Апр 06 2010

Функции timeSetEvent и timeKillEvent

Мультимедийный таймер выполняется в своем собственном потоке. Он отслеживает заданный временной интервал и активизирует по истечении этого интервала таймерное событие. После этого Windows либо вызывает заданную функцию обратного вызова, либо устанавливает заданное событие.
Сервис мультимедийного таймера вызывается с помощью функции timeSet Event:
MMRESULT timeSetEventCUINT uDelay, UINT uResolution.LPTIMECALLBACK lpTimeProc,
DWORD dwUser, UINT fuEvent);
В параметре u Delay указывается задержка активизации таймерного события. В качестве единиц измерения используются миллисекунды. Если значение параметра выходит за пределы задержек, поддерживаемых таймером, то функция вернет код ошибки.
Параметр uResolution содержит разрешение таймерного события в миллисекундах. Чем меньше значение этого параметра, тем выше разрешение. Нулевое значение параметра означает, что периодические события таймера должны появляться с максимально возможной точностью. Однако чем выше разрешение, тем больше будут накладные расходы операционной системы, поэтому желательно выбирать максимальное значение параметра uResolution, при котором удовлетворяются потребности приложения.
Параметр lpTimeProc содержит адрес функции обратного вызова, которая вызывается после установки таймерного события. Если параметр fuEvent содержит флаг TIME_CALLBACK_EVENT_SET или TIME_CALLBACK_EVENT_PULSE, то параметр lpTimeProc интерпретируется как дескриптор объекта «событие».
Параметр dwUser может содержать данные, передаваемые в функцию lpTimeProc, интерпретация которых определяется программистом. В частности, эти данные иногда используются для организации обратной связи с вызывающей функцией.


марта 31 2010

Приложение со стандартным таймером

В качестве примера рассмотрим программу «Прыгающий мячик», в которой имитируется полет мяча в прямоугольном боксе от одной стенки к другой. Ударяясь о стенку бокса, мяч отскакивает под соответствующим углом и продолжает движение в новом направлении. Роль «бокса» в этой программе исполняет клиентская область окна приложения. Чтобы сделать пример более интересным, дополним его двумя требованиями: а) мяч должен вращаться во время движения; б) фон, на котором происходит полет мяча, должен изображать некоторую текстуру.
Контекст устройства в памяти1 (CreateCompatibleDC) для размещения в нем DDB-растра с изображением мяча (SelectObject) и последующего его вывода в контекст дисплея (BitBlt).
Обратите внимание на вызов функции SetGraphicsMode для переключения контекста устройства в графический режим (GM_ADVANCED). Этот режим нужен для использования мировой системы координат и мировых преобразований. В теле функции DrawBall мировые преобразования реализуются вызовом функции SetWorld-Transform, а изменяющиеся значения полей структуры xform обеспечивают эффект перемещения и вращения мяча. Эти преобразования должны использоваться только при выводе изображения мяча. Поэтому перед вызовом SetWorldTransform мы запоминаем текущее состояние контекста устройства с помощью Save DC, а затем восстанавливаем его вызовом RestoreDC. Основные события разворачиваются в блоке обработки сообщения WM_TIMER. Приведенный код вместе с комментариями, на наш взгляд, не требует дополнительных пояснений.


марта 03 2010

Рисование в реальном времени

Разработка авиационной бортовой радиотехнической аппаратуры содержит этап тестирования и взаимной стыковки отдельных подсистем. При этом часто вместо отсутствующей подсистемы применяются программные имитаторы. К приложениям, имитирующим реальную аппаратуру, предъявляются довольно жесткие требования. Например, программный имитатор приемника радиолокационной информации, используемый вместо реального индикатора, должен успевать выводить на экран радиолокационную картинку в том темпе, в котором ее выдает передатчик локатора.
Рассмотрим проблемы, возникающие при создании таких программ, на примере разработки имитатора приемника информации от метеорадиолокатора.


Фев 19 2010

Разработка модели программного имитатора

Настоящий программный имитатор приемника информации от метеорадиолокатора является довольно сложным приложением. К тому же для его функционирования требуется соответствующее аппаратное обеспечение. Поскольку сейчас нас интересуют только вопросы реализации быстрого рисования, в этой главе рассматривается построение упрощенной модели программного имитатора.
В упрощенной модели имитатора приемника информации от метеорадиолокатора мы абстрагируемся от таких проблем, как прием пакетов из цифрового канала связи и их распаковка для извлечения необходимых параметров.
Модель имитатора будет воспроизводить условную радиолокационную картинку в секторе от -60 до +60°, состоящую из четырех «колец» разного цвета.
Период передачи пакетов PACK_PERIOD будет 5 мс. Меню приложения должно позволять выбрать требуемую скорость сканирования из множества значений { 15, 30, 60, 90 } градусов в секунду.
В строке состояния приложения должны отображаться следующие значения: а) скорость сканирования; б) коэффициент размножения лучей; в) расчетное время сканирования всего сектора (в прямом и обратном направлениях); г) фактическое время сканирования всего сектора.


Фев 05 2010

Первая версия модели программного имитатора

Первая версия будет называться ArincReceiverBad. Смысл этого названия станет ясным на этапе тестирования программы.
Создайте новый проект с именем ArincReceiverBad. Скопируйте из папки проекта ToolTip (см. листинг 8.4) в папку проекта ArincReceiverBad файлы KwndEx.h и KwndEx.cpp. Скопируйте из папки проекта KTimer файл KTimer.h. Добавьте скопированные файлы в состав проекта. Также добавьте к настройкам проекта на вкладке Link имена библиотек comctl32.lib и winmm.lib.
Функция GetNextAngle обеспечивает формирование следующего значения кода угла сканирования. При каждом вызове этой функции знак приращения кода угла scanAngle зависит от направления сканирования. При движении по часовой стрелке (FORTH), код угла увеличивается на единицу, при движении против часовой стрелки (BACK) — уменьшается на единицу. На границах сектора сканирования переменная direction изменяет свое значение. Помимо этого вызывается функция SetColorBeamForth или SetColorBeamBack, чтобы заполнить массив cell цветовыми кодами для точек дальности локационного луча. В результате при движении вперед рисуются кольца красного, зеленого, желтого и синего цветов (перечисление идет от центра к периферии). При движении назад рисуются кольца синего, желтого, зеленого и красного цветов.
В реальном имитаторе вызовы функций SetColorBeam Forth и SetColorBeamBack отсутствуют, поскольку массив cell формируется функцией GetPacket.
Рисование луча развертки реализовано в теле функции DrawBeam. Точки дальности локационного луча из массива cell выводятся на экран с помощью функции SetPixel. Для рисования используется контекст устройства с глобальным дескриптором g_hDC. Приложение получает этот контекст один раз при своем старте в блоке обработки сообщения WM_CREATE и освобождает его при завершении работы в блоке обработки сообщения WM_DESTR0Y.
После компиляции проекта перейдем к его тестированию.
На этапе тестирования ресурсоемких приложений очень важно наблюдать за степенью загрузки центрального процессора (ЦП). Операционная система содержит удобный инструмент — системное приложение Диспетчер задач Windows (Task Manager), позволяющее вести такое наблюдение. Для вызова диспетчера задач нужно использовать комбинацию клавиш Ctrl+Alt+ Delete и в появившемся диалоговом окне Безопасность Windows нажать кнопку Диспетчер задач.
После указанных действий на экране появляется окно приложения Диспетчер задач Windows. В строке состояния диспетчера задач отображается текущая загрузка центрального процессора в процентах. Это суммарная загрузка ЦП от всех запущенных процессов. Если переключиться на вкладку Процессы, то можно наблюдать за процентом загрузки ЦП от каждого отдельного процесса.


Янв 14 2010

Запуск IDE. Типы приложений

Запуск Visual C++ осуществляется при помощи команды меню Пуск ► Программы ► Microsoft Visual Studio 6.0 ► Microsoft Visual C++ б.О1. Впрочем, можно просто щелкнуть мышью на соответствующей пиктограмме, если вы позаботились о ее размещении на рабочем столе компьютера.
Окно Project Workspace (окно рабочей области) позволяет эффективно управлять проектом при написании и сопровождении больших многофайловых программ. Пока что (см. рис. П1.1) оно закрыто, но после создания нового проекта или загрузки сохраненного ранее проекта одна из вкладок этого окна будет содержать список файлов, входящих в проект.
Окно Editor (окноредактора) используется для ввода и проверки исходного кода.
Окно Output (окно вывода) служит для вывода сообщений о ходе компиляции, сборки и выполнения программы. В частности, сообщения о возникающих ошибках будут появляться именно в этом окне.
Под заголовком главного окна, как и во всех Windows-приложениях, располагается строка меню. Назначение команд меню и кнопок панелей инструментов мы будем рассматривать по мере необходимости, разбирая основные приемы работы в IDE. Здесь же только заметим, что для кнопок панелей инструментов предусмотрена удобная подсказка. Если пользователь наведет курсор мыши на кнопку и задержит его там на пару секунд, то всплывет окно подсказки, в котором будет описано предназначение кнопки.
Developer Studio позволяет создавать проекты разных типов, ориентированных на различные сферы применения. В этой книге все программные примеры должны строиться в виде проекта типа Win32 Application — empty project.


Следующая страница »