- •Сегменты стека
- •Динамическая память (куча)
- •Объектно ориентированный подход к проектированию системных модулей на основе концепций интерфейсов и реализаций.
- •Родовые данные или данные класса, значение которых относится не к экземпляру, а к типу в целом.
- •Активные объекты
- •Активные объекты с множественными рабочими потоками
- •Посылка синхронных сообщений
- •Выборка сообщений
- •Пример полной и упрощенной выборки
- •Сообщения, определяемые приложением
- •Локальная память потока
- •Трансляторы, компиляторы и интерпретаторы.
- •Общая схема работы транслятора
- •Понятие прохода
- •Генерация кода
- •Многоадресный код с явно именуемым результатом
- •Алгоритм вычисления выражений в полной записи
- •Современные системы программирования
Объектно ориентированный подход к проектированию системных модулей на основе концепций интерфейсов и реализаций.
При реализации сложных проектов требуется предоставить значительную гибкость программистам при сохранении целостной концепции проекта, поскольку dll является самодостаточным блоком исполнения кода, можно компоновать программную систему из таких блоков, связывая их с помощью небольшого количества дополнительных унифицированных операций вызова.
При декомпозиции предметных областей как правило выделяются не функции, а объекты, представляющие собой наборы данных и обрабатывающих их операций. Для обеспечения реентерабельности важно фиксировать контексты вызовов, а для обеспечения жизненного цикла объекта требуется сохранять контекст его данных (состояние).
При доступе к объекту одновременно из разных потоков или рекурсивно из одного потока должно поддерживаться целостное состояние, следовательно реализация вызова должна быть чем – то большим, чем перенос счетчика команд на участок кода, получившего выделенный контекст.
В отличие от процедурного подхода, где сохраняется контекст вызова, а состояние функции во время ее работы не имеет смысла для окружающей среды, экземпляры объектов имеют «жизненный цикл» и внутреннее состояние имеет смысл в том числе во время вызова и между вызовами.
Существует два основных способа организации реентерабельных объектов:
-
Помещение вызовов в очередь в виде пакетов (сообщений);
-
Блокирование одновременного доступа на основе регулярных объектов синхронизации ядра ( mutex).
Обслуживание доступа к объектам поддерживается унифицированным образом независимо от назначения самого объекта, поэтому программный код реентерабельных объектных вызовов также относится к классу СПО и обычно называется middle ware.
Как правило следует различать доступ к объекту с клиентской стороны с целью заставить его изменить свое состояние и реакцию на доступ, т.е. фактическое изменение состояния.
Отсюда следует, что клиенту фактически не требуется иметь доступ к содержанию данных экземпляра объекта, а любую информацию о нем клиент получает через возвращаемое значение вызова, следовательно, объект для клиента состоит из:
-
идентификатор экземпляра;
-
набора функций, относящихся не к экземпляру, а к классу в целом.
При этом каждая такая функция в качестве дополнительного аргумента обязана принимать идентификатор экземпляра.
Библиотека, в которой поддерживается существование объектов, обязана предоставлять клиентам:
-
функцию для создания объекта, возвращение его идентификатора, уникального для каждого экземпляра;
-
таблицу указателей на функции, предназначенные для воздействия на состояние объекта (это можно назвать интерфейсом).
Пример построения объектного модуля на объектно ориентированном языке
Реализовать объект, инкапсулирующий целочисленный счетчик. Состояние – целое число без знака. Набор операций: инициализация, инкремент и декремент. Требуется возврат сообщения об ошибке при попытке декремента нулевого счетчика.
struct Counter
{
unsigned int c;
… //другие поля состояния
};
//функция доступа
typedef void(*Init)(Counter *id, unsigned int value);
typedef void(*Increment)( Counter *id);
typedef int(*Decrement)( Counter *id);
struct CounterAccessTable
{
Init init;
Increment increment;
Decrement decrement;
};
void Get CounterAccessTable (CounterAccessTable *table);
//эта функция экспортируется из библиотеке
void init (Counter *id, unsigned int value)
{
id -> c;
}
void increment (Counter *id)
{
id -> c++;
}
int decrement (Counter *id)
{
return (id -> c>0) ? id -> c--; -1;
}
void Get CounterAccessTable (CounterAccessTable *table)
{
table -> inin = init;
table -> increment = increment;
table -> decrement = decrement;
}
Недостатком такого решения является объявление объекта как структуры данных, поля которой прямо или косвенно доступны клиентам. Проблема имеет два аспект:
-
Устройство объекта доступно для исследования;
-
Невозможна модификация объекта (по крайней мере невозможно добавление полей, изменение аспекта данных).
Вторая проблема должна быть решена, т.к. достижение гибкости модульного системного ПО предполагает возможность модификации реализации без изменения интерфейса.
Требуется отделить процедуры от данных или обработать по той же схеме, которая привела к использованию таблицы функций.

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