Архитектура программного средства

Анализ основных технологий прикладного уровня среды программирования СОМ. Реализация удаленной связи и взаимодействия между процессами. Уникальные идентификаторы для размещения компонента и обращения к нему. Рекурсивная процедура уничтожения цвета.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 01.03.2014
Размер файла 83,2 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru

Размещено на http://www.allbest.ru

1. Технологии прикладного уровня

Компонентная модель.

Для начала, чтобы вам было легче разобраться в некоторых технологиях Microsoft, мы опишем их основу -- СОМ. Эта глава не претендует на полноту материала -- здесь представлены только основные концепции, без которых разработчик не может приступить к проектированию архитектуры приложения. В дальнейшем изучении СОМ вам помогут книги, перечисленные в библиографическом списке в конце книги. Существует еще одна объектная модель -- Common Object Request Broker Architecture (CORBA). Подробно она описана в книге Алена Поупа (Alan Pope) «The CORBA Reference Guide» (Addison-Wesley, 1998).

Почему COM? Главная цель COM -- предоставить разработчикам возможность создавать приложения, собирая их из уже готовых частей-компонентов. Компоненты -- это не что иное, как физическая реализация бизнес-объектов. Например, в приложении для заполнения бланков заказов можно использовать компонент-таблицу, упрощающий ввод заказываемых товаров. Другой компонент мог бы сам находить город клиента по введенному почтовому индексу. Еще один компонент мог бы рассчитывать налог с продаж. Однако при создании такого приложения в реальности разработчики сталкиваются с некоторыми техническими трудностями. Во-первых, непонятно, как разместить компонент на компьютере или в сети и, если это удалось, как его запустить. Эти вопросы входят в компетенцию службы каталога для компонентов. Если нет какого-либо стандарта, резко возрастают расходы на изучение компонентов. Кроме того, из-за несогласованности алгоритмов, размещающих компоненты и создающих объекты, затрудняется повторное использование готовых компонентов. Ведь приложение должно уметь находить и выполнять не только компоненты, созданные для внутреннего применения, но и компоненты от сторонних производителей. Вторая трудность состоит в создании стандартов взаимодействия приложений с компонентами. Как и в предыдущем случае, если таких стандартов нет. Накладные расходы на изучение использования компонентов будут препятствовать повторному использованию кода. Идеальный механизм взаимодействия компонентов не должен зависеть от их местонахождения; он должен работать независимо от того, существует ли этот объект в процессе собственного или другого приложения на локальном или на удаленном компьютере. Реализация удаленной связи и взаимодействия между процессами очень сложна, но стандарты могут значительно сократить время, затрачиваемое на создание такого кода. Третья трудность -- языковая независимость. Все составляющие объекта -- выделение памяти, названия методов, типы параметров, соглашения о вызовах и т. д. -- должны быть определены так, чтобы объект можно было создать на одном языке программирования, а вызвать его из приложения, написанного на другом языке. При этом разработчики не должны тратить время на выяснение языка или инструментальных средств, с помощью которых был создан компонент. Без широкой поддержки инструментальных средств разные объектные модели разбивают рынок компонентов на мелкие части, что увеличивает затраты на поиск, приобретение и разработку компонентов. И наконец, последняя проблема -- сохранение возможности создания новых версий приложений и компонентов. Приложения, разработанные в разное время, могут использовать одинаковые компоненты, что ведет к конфликтам при запуске на одном компьютере. Кроме того, по мере совершенствования компонентов должна сохраняться совместимость версий. Из-за постоянных обновлений может возникнуть проблема исправления существующих компонентов, расширения их функций и замены новыми компонентами, Теперь мы обсудим основные элементы и термины СОМ, часто используемые при разработке приложений.

Объекты.

«Объект» -- один из самых перегруженных терминов программирования. Но, как и в большинстве объектно-ориентированных моделей, СОМ-объекты -- это экземпляры некоторого класса, представляющего какой-то реальный объект. Точное определение класса мы дадим позже, однако можно сказать, что класс -- это тип объектов. Например, рассмотрим три класса с разными характеристиками: Customer (клиент), Order (заказ) и SalesTaxCalculator (подсчет налога с продаж). В таком случае каждый объект Customer представляет собой какого-либо реального клиента, каждый объект Order -- экземпляр заказа и т. д. Каждый объект обладает идентификатором, состоянием и поведением. Идентификатор -- это уникальное имя или метка, отличающие один объект от другого. Состояние -- данные объекта. Поведение -- набор методов, запрашивающих или изменяющих состояние объекта. Чтобы разобраться в этих понятиях, рассмотрим объекты C++, являющиеся экземплярами классов C++. В каждом классе определены переменные и методы, присущие только объектам данного класса. При создании объекта для его переменных-членов выделяется непрерывный блок памяти, адрес этого блока становится идентификатором объекта, а его содержимое -- состоянием. Размешенные в других блоках памяти методы определяют поведение объекта. Многие объектные модели языков программирования похожи на модель из C++, но модель СОМ отличается от нее. Напомним две трудности, связанные с СОМ, -- независимость от языка программирования и местонахождения. Оказывается, что при удаленном вызове и взаимодействии между процессами нельзя однозначно идентифицировать объект по его адресу в памяти. Кроме того, достичь совместимости методики размещения переменных объекта в памяти для всех языков программирования и инструментальных средств практически невозможно. Из-за этих трудностей подход к объектам в СОМ отличается от традиционного. В СОМ открытый интерфейс объекта и его реализация полностью разделены. Приложения могут взаимодействовать с СОМ-объектами только с помощью их открытых интерфейсов, используя при этом стандартный указатель на интерфейс. По этой причине СОМ игнорирует местонахождение состояния объекта и внутренние блоки памяти. Кроме того, так как указатель на интерфейс единственное средство доступа к определенному объекту, то и идентификатор объекта должен быть связан с этим указателем.

Интерфейсы.

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

* иметь уникальный идентификатор;

* быть производным от интерфейса lUnknown;

* не должен изменяться после публикации.

Идентификаторы COM.

Для размещения компонента и обращения к нему необходимы уникальные идентификаторы. Можно было бы использовать строковые идентификаторы, но при этом возникает несколько проблем. Одна из самых опасных проблем связана со сложностью выбора действительно уникального идентификатора. Даже при наличии соглашения об именах остается возможность, что какой-нибудь разработчик использует уже применяемый идентификатор с другой целью. Для гарантии уникальности имени префиксы должны выдаваться каким-либо центральным органом -- например, по одному префиксу для каждой компании. Этим компаниям, в свою очередь, потребуется централизованный реестр имен, который поможет им не допустить появления одинаковых названий. Как видите, простой подход оказывается слишком сложным. Вместо символьных имен в СОМ применяются глобально уникальные идентификаторы (Globally Unique Identifier, GUID). Это генерируемые системой 128-разрядные целые числа, уникальность которых обеспечивается алгоритмом их генерации. Примечание Согласно спецификации СОМ, можно без повторения создавать 10000000 идентификаторов в секунду на каждом компьютере в течение 3240 лет, GUID можно сгенерировать с помошью утилиты GUIDGEN из комплекта Microsoft Platform Software Development Kit (SDK). Это приложение создает GUID, вызывая функцию прикладного интерфейса CoCreateGuid, после чего предлагает выбрать способ его представления. Например, если выбрать статический постоянный (static const) идентификатор -- обычный метод для включения идентификатора в файлы исходного кода на C++, -- получится следующее: //{4C5ECD6D-9DDF-11D4-881F- 0020AF15C468}.

static const GUID GUID_Semple= {0x4c5ecd60 0x9dcf. 0x11d4 {Oxlf, 0x0, 0x20, Oxaf. 0x15, Охс4, 0x67 } }:

Первая строка содержит GUID в символьной форме, в которой его обычно и видят пользователи. Во второй строке GUID представлен R виде константы, которую можно использовать в коде C++. Большинство средств разработки автоматизируют процесс создания каркаса СОМ-компонентов. Они же генерируют соответствующий GUID в формате этого каркаса.

Каждый интерфейс идентифицируется по его GUID. Чтобы обратиться к интерфейсу, мы используем его GUID, который в данном случае называется идентификатором интерфейса (interface identification.I1D). В качестве IID могут выступать, например, такие значения:

{45D3F4BO-DB76-lldl-AA()6-0040052510Fl} или {45D3F4B1-DB76-lldl-AA06-0040Q52510Fl}.

Для простоты каждый интерфейс согласно стандарту должен иметь символьное название. Обычно такие названия начинаются с буквы «1» -- например, IComputerSalesTax. Конечно, уникальность символьных имен не гарантируется, но маловероятно, что два разных интерфейса с одинаковыми названиями будут использоваться в одном исходном файле.

Описание интерфейса.

Может возникнуть вопрос: как определять интерфейсы, чтобы разработчики компонентов знали, как их реализовать, а разработчики приложений -- как их использовать? В СОМ нет ограничений на средства определения интерфейсов, однако на практике СОМ - интерфейсы обычно описываются на языке определения интерфейса (Interface Definition Language, IDL). Как и C++, IDL -- это язык, описывающий точный синтаксис интерфейса. Определение интерфейса начинается с ключевого слова, перед которым в квадратных скобках помешены атрибуты интерфейса. Если атрибутом является объект, следует использовать IDL- расширений СОМ; атрибут UU1D задает идентификатор описываемого интерфейса, Атрибут называется UUID по той причине, что язык описания интерфейсов СОМ базируется на версии IDL Open Software Foundation. В этой версии вместо термина GUID применяется термин «универсально униксмьный идентификатор» (Universally Unique Identifier, UUID).

He все языки программирования поддерживают все типы данных, которые можно определить с помощью IDL, поэтому большинство интерфейсов использует ограниченный набор типов данных. Подробнее этот вопрос обсуждается далее в этой главе. Методам СОМ можно передавать любое количество параметров, а возвращать они могут данные любой сложности. Помимо типа данных и названия, для каждого параметра можно определить дополнительные атрибуты, несущие информацию о способах копирования данных. IDL -- удобный текстовый формат документирования синтаксиса интерфейса. С помощью компилятора Microsoft IDL (MIDL) код IDL можно компилировать, При этом будут сгенерированы файлы определения интерфейса, понятные разным средствам разработки:

* заголовочный файл -- в заголовочных файлах определены типы IDL, которые могут использоваться при объявлении указателей на переменные интерфейса или при наследовании класса; эти файлы можно включать в программы на С и С--г;

* библиотека типов -- двоичное представление кода IDL, которое используется в языке программирования, например, в Microsoft Visual Basic, для выяснения синтаксиса описанного в ней интерфейса;

* исходный код DLL -- заместителей и представителей -- исходный код библиотек, которые служат для удаленного вызова методов и взаимодействия между процессами.

Несмотря на простоту использования, IDL -- все еще новый язык для многих разработчиков, поэтому в большинство средств разработки включены функции, облегчающие его применение. Некоторые системы, например. Visual Basic, полностью скрывают 1DL от разработчиков, позволяя определять интерфейсы с помощью синтаксиса системы и автоматически генерируя библиотеки типов. Другие инструментальные средства позволяют создавать файлы IDL c помощью мастеров, помогающих определить интерфейс и его методы.

Определение интерфейса посредством IDL -- лишь первый шаг на пути к языковой независимости. Имея файл IDL или сгенерированные из него заголовочный файл или библиотеку типов, можно создать интерфейсное или клиентское приложение при условии, что выбранный язык программирования поддерживает используемые типы данных. Но, чтобы клиентский компьютер и разработанная программа могли взаимодействовать, они должны одинаково «понимать» назначение интерфейсного указателя и способ вызова методов.

СОМ как двоичный стандарт.

Компонентная модель является двоичным стандартом благодаря ориентации на спецификации и наличию реализации. СОМ основана на спецификации, так как СОМ-объекты не зависят от языка программирования и местонахождения. Интерфейс СОМ-компонента можно определить с помощью IDL, соответствующего заголовочного файла или библиотеку типов.

Модель СОМ основана на реализации, так как обладает системными сервисами размещения и вызова компонентов. Кроме того, Технологии прикладного уровня СОМ поддерживает удаленный вызов и взаимодействие между процессами. СОМ определяет точное двоичное представление интерфейса, в соответствии с которым все средства разработки должны создавать интерфейсы объектов.

Интерфейсный указатель клиента в действительности ссылается на таблицу указателей, называемую виртуальной таблицей (viable). Каждый указатель этой таблицы ссылается на двоичный код метода интерфейса точно так же, как это происходит в таблице виртуальных функций C++.

Каждый СОМ-объект содержит указатель на виртуальную таблицу для всех поддерживаемых им интерфейсов. Клиент, запрашивающий интерфейсный указатель на объект, получает указатель на указатель в виртуальной таблице, а не сам указатель на виртуальную таблицу. Это происходит из-за того, что компонент должен каким-либо образом идентифицировать объект, с которым он работает.

При создании СОМ-объекта выделяется один блок памяти для указателей на виртуальную таблицу и свойств (данных) объекта. Компонент может идентифицировать объект, распознав связь между положением указателя на виртуальную таблицу и всем блоком памяти объекта. В дальнейшем СОМ с помощью интерфейсного указателя устанавливает, что первый параметр, передаваемый методу, является указателем на данный объект.

К счастью, большинство языков и средств программирования, поддерживающих СОМ, автоматически преобразуют интерфейсные указатели и виртуальные таблицы в понятия, свойственные данным средствам разработки. Например, в языке C++ интерфейсы соответствуют абстрактным базовым классам, наследуя которым, можно реализовать интерфейсы. Вызов методов СОМ с помощью интерфейсного указателя полностью идентичен вызову методов C++ посредством указателя на объект. Приведем другой пример: интерфейсы Visual Basic практически не доступны из самого языка Visual Basic. Их можно реализовать, применив ключевое слово implements. Чтобы использовать СОМ-объект, нужно сначала определить переменную типа «интерфейс», а затем создать объект. После такой процедуры можно вызывать функции как обычно.

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

Интерфейс IUnknown.

В виртуальной таблице содержатся три метода -- Query Interface, Add-Ref и Release, не определяемые разработчиком.Эти методы интерфейса I Unknown определяют основное поведение всех СОМ-интерфейсов, причем клиенты могут рассчитывать на это повеление, так как все СОМ-интерфейсы являются производными от lUnknown. С его помощью устраняются технические трудности, связанные с взаимодействием объектов; кроме того, он реализует три важные функции: перемещение по интерфейсам, выяснение их версий и управление временем существования объекта.

Перемещение по интерфейсам.

Для перемещения по интерфейсам служит метод Querylnterface. Как упоминалось выше, СОМ-объекты могут поддерживать несколько интерфейсов. В этом случае, если у разработчика есть один интерфейсный указатель и он хочет получить другой, он может запросить его у объекта с помощью метода Querylnterface. Этот метод поддерживается всеми интерфейсами как производными от Unknown.

При использовании метода Querylnterface клиент передает объекту соответствующий идентификатор интерфейса IID. Если объект поддерживает данный интерфейс, он возвращает указатель на него. В противном случае объект возвращает ошибку. Querylnterface -- это невероятно мощный механизм, позволяющий независимо созданным клиентам и компонентам согласовывать способ взаимодействия. С его помошью устраняются и проблемы определения версий, описанные в следующем разделе.

Версии интерфейса.

Из-за того, что компоненты и приложения создаются независимо друг от друга, опубликованный интерфейс должен быть неизменным. Любые модификации, даже числа методов, могут привести к проблемам, Например, новое клиентское приложение может ошибочно считать, что интерфейс включает пять методов. Если оно обратиться к устаревшему компоненту всего с четырьмя функциями, возникнет ошибка. Именно из-за возможности таких конфликтов СОМ-интерфейс не должен изменяться.

Новый интерфейс считается новой версией. Существующие приложения, скорее всего, не будут совместимы с ним, но так как исходный интерфейс остается неизменным, реализация интерфейсов в компонентах не повлияет на эти приложения. В новых программах можно реализовать поддержку обновленных интерфейсов и разрешить им доступ к новым функциям. Если же клиент обратится к старому компоненту, онсможет безопасно узнать об отсутствии новыхметодов с помощью Queryhiterface.

Таким образом, СОМ-интерфейс нельзя изменять. При создании его новой версии нужно просто добавить в компонент новый интерфейс, сохранив поддержку старого.

Время существования объекта.

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

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

Классы.

СОМ-объекты -- это экземпляры СОМ-классов, которые в свою очередь, представляют собой поименованную реализацию одного или нескольких СОМ- интерфейсов. Имена классам назначаются-с помощью одной из разновидностей GUID -- идентификаторов класса (CLSID). Как и IID, CLSID уникальны, но пользоваться ими сложнее. Поэтому СОМ-классам назначают и символьные имена, называемые программными идентификаторами (ProgID).

С каждым СОМ-классом связан объект класса (так называемая фабрика классов), способный создавать его экземпляры. В спецификациях СОМ определены стандартная функция API, создающая объекты класса (CoGetClassObject), и стандартный интерфейс для передачи им сообщений (ICIassFactory). Таким образом, клиентам достаточно одного механизма создания СОМ-объекта любого типа. Самый важный метод интерфейса ICIassFactory -- Createlnstance, создающий объект и возвращающий интерфейсный указатель. Существует два способа создания СОМ-объекта: клиент может вызвать функцию CoGetClassObject, получив таким образом указатель на интерфейс ICIassFactory, либо передать интерфейсный указатель объекту с помощью метода Createlnstance интерфейса ICIassFactory с последующим удачен нем этого интерфейса. Так как второй способ применяется довольно часто, для обле гчения труда разработчиков была добавлена функция CoCreatelnstanctiEx, сама выполняющая нужные вызовы.

СОМ-классы отличаются от классов большинства языков программирования тем, что после создания объекта его класс никого не интересует. Взаимодействие с объектом осуществляется с помощью открытых интерфейсных указателей, которые не распознают закрытых классов реализации, использованных для создания объекта. Строгое разделение интерфейса и его реализации -- ключевое свойство СОМ. Эта концепция «черного ящика» значительно упрощает написание клиентов, так как им не нужно знать, как работают компоненты.

Компоненты.

СОМ-компоненты -- это двоичные модули для создания СОМ - объектов. Компонент, отвечающий за определенный CLSID, содержит СОМ-класс, код, реализующий объект класса и, как правило, код, добавляющий соответствующие записи в системный реестр.

В Microsoft Windows 95, Windows 98 и Windows NT существует три типа компонентов: сервисы, исполняемые файлы и библиотеки. Компоненты - сервисы стоит применять, если они должны быть запущены все время, даже если никто не зарегистрирован в системе. Исполняемые файлы применяются, если помимо создания СОМ-объектов приложение должно обладать пользовательским интерфейсом. Примером такого компонента является Microsoft Word. В большинстве же случаев -- например, в трехуровневых приложениях -- компоненты собираются в виде библиотек DLL. Элементы управления ActiveX презентационного уровня и транзакпионные компоненты, реализующие бизнес-функции, также реализуются в виде библиотек

Кроме того, компоненты можно разделить на три категории но их отношению к клиенту.

* Внутрипроцессные -- запускаются в том же процессе, что и клиент. Они реализуются в виде DLL.

* Локальные компоненты -- запускаются в разных процессах на одном клиентском компьютере. Они могут быть как исполняемыми файлами, так и сервисами.

* Удаленные компоненты -- работают на удаленных компьютерах. Такие компоненты могут быть реализованы в виде исполняемых файлов, сервисов и библиотек. Запускают DLL на удаленном компьютере с помощью процесса-представителя или приложения, способного запускать DLL. И в СОМ, и в MTS существуют стандартные представители DLL-компонентов.

Далее в этом разделе, посвященном СОМ, мы рассмотрим компоненты, реализованные в виде библиотек, так как они чаще всего встречаются в многоуровневых приложениях.

Структура DLL-компонентов.

Помимо реализации СОМ-классов и объектов, что обязательно для компонентов всех типов, в DLL-компоненте должны присутствовать четыре точки входа:

* DHGetClassObject -- возвращает интерфейсный указатель на объект класса, определенного в компоненте;

* DllCanUnloadNow -- показывает, активны ли объекты, созданные компонентом. В случае их активности библиотека должна оставаться в памяти; в противном случае ее можно выгрузить, освободив ресурсы компьютера;

* DllRegisterServer -- создает элементы реестра, необходимые СОМ- классам компонента;

* DHUn register Server -- удаляет все элементы реестра, созданные с помощью DllRegisterServer. СОМ самостоятельно вызывает функции DllGetClassObject и DUCanUnloadNow, так что приложения не должны вызывать их напрямую. Функции DllRegisterServer и DMUnregisterServer обычно вызывают программы установки и средства разработки.

Потоки.

СОМ поддерживает несколько потоковых моделей для компонентов. Потоковая модель определяет количество запушенных потоков и способы синхронизации объектов. Windows 95, Windows 98 и Windows NT -- многопоточные среды, поэтому компоненты для них нужно писать аккуратно.

Все потоковые модели СОМ основаны на понятии отделенного потока (apartment). Отделенный поток -- это контекст исполнения объекта. Каждый объект все время своего существования размещается только в одном отделенном потоке; потоки же, в свою очередь, входят в состав процесса. Кроме того, до вызова СОМ-методов потоки данного процесса должны быть связаны с отделенным потоком с помошью функций reinitialize или CoInitializeEx. Все обращения к объекту происходят из его отделенного потока. Если приложение должно вызывать функции в разных потоках, СОМ синхронизирует доступ к объекту. Кроме того, при использовании одиночных отделенных потоков (Single-Threaded Apartment, STA) для межпотоковых вызовов необходим маршалинг. Он подробно описан в разделе «Удаленная активация и маршалинг». Кратко же можно сказать, что маршалинг -- это процесс, перехватывающий вызовы, преобразующий стек вызовов в стандартный формат и после выполнения некоторых действий снова преобразующий его в вызовы методов отделенного потока объекта. Поэтому встроенные в процесс межпотоковые вызовы могут значительно снизить производительность приложения, что еще раз свидетельствует о важности знания потоковых моделей СОМ.

В Windows 95, Windows 98 и Windows NT COM поддерживает два типа отделенных потоков. Одиночный отделенный поток связан с одним потоком и создается при вызове функций Colnitialize или Со[nitializeEx. В процессе могут существовать несколько таких потоков; первый из них называется главным. У процесса может быть и один множественный отделенный поток, с моделью которого можно связать несколько потоков. Чтобы воспользоваться моделью множественного отделенного потока, называемой также моделью свободных потоков, нужно присвоить ключу реестра ThreadModel значение FREE.

По умолчанию, если раздел реестра ThreadModel отсутствует, с STA на протяжении всего времени существования связан один поток, причем одновременный доступ к объектам модели отделенного потока, размещенным в STA, невозможен, так как они запущены в одном потоке. Независимоот количества объектов в отделенном потоке, за один раз может осуществляться вызов только одного метода. Кроме того, в данный момент времени в STA разрешено существование только одного экземпляра объекта. Таким образом, облегчается труд разработчиков, которым не нужно синхронизировать доступ к состоянию каждого объекта -- при необходимости можно использовать локальную память потока. Чтобы повысить масштабируемость приложения, можно присвоить ключу реестра ThreadModel значение Apartment, что позволит создавать несколько экземпляров объекта в одном STA. При этом глобальные данные компонента и точки входа DLL должны быть реентерабельными.

Синхронизация в STA основана на сообщениях Windows. Вызовы ставятся в очередь специальных сообщений и обрабатываются созданным СОМ скрытым окном. В результате у потоков, связанных с STA, должны быть циклы обработки сообщении, получающие сообщения из очереди, транслирующие их и передающие другим частям приложения. Если у потока нет такого цикла, вызовы не обрабатываются. Модель синхронизации STA не препятствует повторному входу, а наоборот обеспечивает реентерабельность. Она полностью совпадает с моделью, используемой в оконных процедурах. При вызовах методов из других потоков или процессов СОМ продолжает передавать сообщения, поэтому STA может обработать входящие вызовы и гарантировать ответ окон потока. Вызванные при этом объекты могут без проблем обращаться к другим объектам.

Компоненты, удовлетворяющие модели отделенных потоков, легко написать, но из-за ограничений на параллельные операции их производительность в многопользовательской среде невелика. В таком случае лучше подойдет модель свободных потоков. СОМ не синхронизирует доступ к объектам во множественном отделенном потоке, для обслуживания параллельных вызовов к которому потоки создаются динамически. Это позволяет получить одновременный доступ к объектам свободных потоков, что увеличивает производительность приложения. Создать реентерабельный код довольно сложно -- ведь глобальные переменные и состояния объектов должны быть защищены. Кроме того, нужно убедиться в реентерабельности функций библиотек компоновки. СОМ значительно облегчает эту работу, предоставляя возможность выбора потоковой модели при написании кода и разрешая все несоответствия между объектной моделью и потоковой моделью, поддерживающей вызовы. Эта функция особенно интересна для встраиваемых в процесс компонентов, которые обычно используют потоки процесса клиента, а не создают новые. Клиент может создать объект, вызвав методы Colnitialize или CoInitializeEx и определив тем самым отделенный поток, связанный с вызывающим потоком. Но возникает вопрос: как Разработка СОМ убедится в том, что отделенный поток, из которого осуществлен вызов, совместим с потоковой моделью нашего объекта? При создании компонента поддерживаемая им потоковая модель помешается в элементе реестра раздела InprocServer32: ThreadingMode-"AparTTient" По значению элемента ThreadingModel COM может определить, в каком отделенном потоке должен быть создан объект. Например, если вызов осуществляется из STA и значение элемента ThreadingModel равно Apartment, объект будет создан в обращающемся к нему STA. Все вызовы объекта будут прямыми, поэтому не потребуется маршал инг. Если же вызов осуществляется из множественного отделенного потока и элемент ThreadingModel имеет значение Apartment, объект будет создан в новом STA, а все обращения к нему будут подвергаться маршалингу.

Большинство современных приложений и компонентов либо поддерживают модель отделенных потоков, либо являются однопоточными (используют главный STA). Первые характеризуются оптимальным сочетанием простоты разработки и производительности. Далее в этой главе описаны функции MTS, позволяющие масштабировать такие компоненты для работы с большим числом пользователей.

Модель программирования СОМ.

Модель программирования СОМ довольно мошна, но в то же время проста, хотя иногда трудно разглядеть эту простоту за всеми ее сервисами. Поэтому мы не будем обсуждать их, а поговорим о самой модели рограммирования, COM, OLE и ActiveX

Возможно, разработчики лучше знакомы с OLE и ActiveX, чем с СОМ, поэтому нетрудно запутаться в значении этих терминов и их связи друг с другом. И это не удивительно, ведь за последнюю пару лет Microsoft изменила определения этих терминов, хотя сами технологии не менялись. Поясним различия.

* СОМ -- фундаментальная модель компонентных объектов, появившаяся в 1992 году. В СОМ входят только элементы, определенные в ее спецификации, которую можно изучить на Web-узле Microsoft (www.microsofl.com/com/resources/specs.asp).

* OLE -- надстройка над COM и, фактически, механизм реализации составных документов. Примером использования OLE может служить документ Microsoft Word, в который вставлена таблица Excel.

* ActiveX -~ маркетинговое название появившихся в 1996 году интернет-технологий на основе СОМ. В то немного безумное время все основанные на СОМ элементы, собирались под зонтиком ActiveX, что только внесло дополнительную путаницу. Сейчас все более или менее нормализовалось, и термин ActiveX используется только для обозначения элементов управления ActiveX -- специфической технологии на основе СОМ, применяемой для работы с программными элементами управления. Они используются, например, при помещении элемента управления в форму Visual Basic или при встраивании тэга <OBJECT> в HTML-страницу.

Автоматизация.

Изучая СОМ, мы познакомились с отличительной чертой СОМ- объектов и интерфейсов -- клиентские приложения еще при сборке должны знать СОМ- интерфейсы, которые они будут использовать. Ведь программа не может создать произвольный СОМ-объект и обращаться к его интерфейсам, она может обращаться только к интерфейсам, о которых имела представление при своем создании. При таком положении дел полезно определять тип используемых объектов и соответствующие им интерфейсы во время выполнения. Эту возможность предоставляет технология автоматизации (Automation), изначально разработанная для программного управления приложениями из макросов и сценариев, например, в Excel или Word. На момент публикации данной книги в Word и Excel использовался общий язык создания макросов -- Microsoft Visual Basic for Applications. Такие языки не могут содержать информацию обо всех интерфейсах объектов, поэтому она предостаапяется приложениям с помощью автоматизации.

Диспетчерские интерфейсы.

Как и в случае обычных СОМ-интерфейсов, интерфейсы автоматизации, включая стандартные -- для создания и перемещения по информации о типе, -- можно определять с помощью IDL. Однако вместо ключевого слова interface применяется ключевое слово dispinterface. Оно указывает, что интерфейс реализован на основе IDispatch, и поэтому можно использовать только типы, поддерживаемые автоматизацией. Методы диспетчерских интерфейсов не заносятся в виртуальную таблицу интерфейса.

Благодаря ключевому слову dispinterface разработчики могут явно отделить свойства от методов: свойство представляет собой атрибут. а метод -- действие. Например, рассмотрим диспетчерский интерфейс Rectangle, содержащий свойства Height и Width и метод Move. причем свойства реализованы в виде пары функций доступа: одна из них считывает значение, другая его записывает. Обе функции имеют один и тот же диспетчерский идентификатор DISPID; для определения типа операции -- чтение или запись -- методу Invoke передается специальный флаг. Возможность таких действий, способных упростить не только синтаксис свойств, но и применение объектов, полез на языках, поддерживающих автоматизацию. Например, в Microsoft Visual Basic Scripting Edition (VBScript) свойства практически неотличимы от переменных:

set rect - CreateObject("Shapes.Rectangle").

ect.Left = 10.

rect.Top = 10.

act. Height = 30.

ect.Width = rect.Height.

Как уже упоминалось выше, необходимость вручную кодировать определения интерфейсов на IDL возникает редко. Среды разработки, например, Visual Basic, позволяют делать это посредством стандартных конструкций языка, сразу же создавая библиотеки типов. В некоторых других средах такая работа выполняется мастерами, генерирующими правильно отформатированные IDL-файлы, которые можно скомпилировать в библиотеку типов с помощью M1DL.

Двойные интерфейсы.

Для компилируемых клиентов раннее связывание значительно эффективнее позднего. Однако, если приложения написаны на языке, поддерживающем связывание по виртуальной таблице, вызов метода Invoke может привести к увеличению накладных расходов. Эту проблему решают двойные интерфейсы (dual interfaces), обладающие характеристиками как интерфейсов на основе виртуальных таблиц, так и диспетчерских интерфейсов.

Двойные интерфейсы определяются с помощью ключевого слова IDL interface. Все они имеют атрибут dual, показывающий, что типы параметров методов интерфейса должны поддерживаться автоматизацией. Кроме того, все они являются производными от IDispatch. Методы, определенные в двойном интерфейсе, входят в его виртуальную таблицу, поэтому клиенты, использующие связывание по виртуальной таблице, могут вызывать их напрямую. Кроме того, в двойных интерфейсах присутствует и функция Invoke, поэтому клиенты, использующие только раннее или позднее связывание, также смогут работать с ними. Метод Invoke для определения вызываемой функции по-прежнему использует идентификатор DISPID.

Как видите, практически нет причин, по которым стоило бы отказаться от применения двойных интерфейсов. На момент публикации этой книги почти все средства разработки поддерживали их, а большинство совместимых с СОМ пакетов генерировали их по умолчанию. Двойные интерфейсы позволили без дополнительных усилий разработчиков повысить производительность клиентских приложений, использующих связывание по виртуальной таблице. Кроме того, двойные интерфейсы могут использовать маршалинг. что избавляет от необходимости установки DLL-заместителей или представителей на клиентских компьютерах.

СОМ в распределенных средах.

При изучении модели программирования СОМ мы выяснили, что СОМ-компоненты можно без дополнительных усилий запускать на удаленных компьютерах. Независимость от местонахождения реализована на уровне потоков, процессов и компьютеров. Однако при вызове компонентовна разных компьютерах следует рассмотреть некоторые дополнительные вопросы. В этом разделе мы опишем распределенную компонентную модель (Distributed COM, DCOM) и механизм реализации независимости от местонахождения.

При выполнении удаленных вызовов возникают вопросы, которые просто не встречаются в случае одного компьютера. Во-первых, по причинам безопасности системы открытый доступ к установленным компонентам может быть нежелателен. Во-вторых, пользователи, обладающие правом доступа к этим компонентам или к компьютерам, на которых они установлены, должны быть обучены работе с ними.

Защита.

В СОМ определены стандартные средства взаимодействия объектов со службами защиты операционной системы. При этом модель защиты СОМ не зависит от существующих служб ОС.

Средства защиты СОМ решают два вопроса: кому разрешено запускать компоненты и как обеспечить безопасность вызовов интерфейсного указателя (должна обеспечиваться как безопасность активации, так и безопасность вызовов).

2. Практическая часть

Формулировка задания.

Игра "See and Click”. Полезная игра на развитие зрения памяти. Нужно уничтожить все одинаковые по цвету кубики стоящие рядом друг с другом. Суть игры в том чтобы на поле осталось как можно меньше кубиков.

Технические требования.

Данная программа была разработана в системе программирования Borland Delphi 7.

Системные требования:

Windows NT / 9X;

Pentium 133 МГц;

8 Мб RAM;

Video card 4 Мб;

Свободное место на диске 1 MB;

Мышь.

Структура проекта.

Проект содержит следующие файлы:

See and Click.exe,

'Unit1.pas' {основная форма}.

'Unit2.pas' {About форма}

'Unit3.pas' {форма выбора сложности}

'Unit4.pas' {форма рекордов}

'Unit5.pas' {форма для ввода имени}.

Описание структуры используемых типизированных файлов

В программе был использован один файл содержащих информацию нужную для корректной работы программы:

`records.rog'- содержат информацию о лучших игроках трех уровней сложности. Состоят из записей:

TF = record.

Lvl : integer; {поле для записи уровня}

str : string[50]; {поле для записи времени и имени пользователя}

end;

Реализация некоторых методов программы.

Процедура заполнения игрового поля:

procedure NEW;

var i,j:integer;

begin

for i:=0 to 19 do

for j:=0 to 39 do

begin

Field[i,j]:=random(5);

case field[i,j] of

0: DG1.Canvas.Brush.Color:=clGreen;

1: DG1.Canvas.Brush.Color:=clRed;

2: DG1.Canvas.Brush.Color:=clYellow;

3: DG1.Canvas.Brush.Color:=clBlue;

4: DG1.Canvas.Brush.Color:=clBlack;

end;

DG1.Canvas.FillRect(DG1.CellRect(i,j));

end;

end;

Рекурсивная процедура уничтожения цвета:

Procedure dead(x, y, colr: integer);

begin

dg1.Canvas.Brush.Color := clWhite;

dg1.Canvas.FillRect(dg1.CellRect(x, y));

Field[x, y] := -1;

if (Field[x + 1, y] = colr) and (x + 1 <= 19) then

deda(x + 1, y, colr);

if (Field[x, y + 1] = colr) and (y + 1 <= 39) then

deda(x, y + 1, colr);

if (Field[x, y - 1] = colr) and (y - 1 >= 0) then

deda(x, y - 1, colr);

if (Field[x - 1, y] = colr) and (x - 1 >= 0) then

deda(x - 1, y, colr);

end;

Инструкция пользователя.

Для запуска программы требуется запустить файл See and Click.exe.

После чего вы увидите основную форму:

прикладной идентификатор рекурсивный удаленный

Рис. 1.

Затем чтобы начать игру необходимо выбрать меню file закладку new game Рис. 1.

Затем появиться окно выбора сложности программы:

Рис. 2

Суть игры заключается в том, что нужно закрасить все одинаковые рядом стоящие квадратики, как можно за короткий промежуток времени.

После завершения игры появиться форма ввода имени для сохранения вашего времени в истории:

Рис. 3

затем появится таблица рекордов с тремя уровнями сложности:

Рис. 4

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.