Функции управления памятью

Вполне возможно, что эти функции вам не понадобятся, поскольку резидентный ARexx-процесс сам отслеживает необходимость резервирования и/или освобождения памяти и вызывает с этой целью различные системные функции по мере необходимости. Функции управления памятью покажутся знакомыми тем, кто программирует на С или ассемблере, поскольку их С-шные и ассемблерные имена и аргументы весьма схожи с ARexx-овскими. Тем не менее, использование явного управления памятью из ARexx-a представляет некоторый интерес для специальных случаев программирования, когда встроенных в язык высокоуровневых средств оказывается недостаточно для решения возникающих проблем.

Следует только заметить, что функции управления памятью - самые опасные из всех функций ARexx-a, поскольку они "вклиниваются" в работу резидентного ARexx-процесса, полагающего, что он и только он вправе предоставлять память отдельным ARexx-программам, работающим под его отеческой опекой.

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


ALLOCMEM()
res = ALLOCMEM(<длина>,<атрибуты>)

Функция резервирует блок памяти требуемой "длины" с заданными "атрибутами". В случае удачи возвращается начальный адрес блока, иначе - нулевое значение. Значение "атрибутов" совпадает с соответствующим значением, передаваемым функции библиотеки exec.library AllocMem().

Каждый вызов ALLOCMEM() должен обязательно уравновешиваться соответствующим вызовом функции FREEMEM() перед выходом из программы!


BADDR()
res = BADDR(<BCPL_адрес>)

Функция преобразует BCPL-адрес в С-адрес, умножая аргумент на 4.


EXPORT()
res = EXPORT(<адрес>[,<строка>][,<длина>][,<наполнитель>])

Функция копирует область памяти из "строки" по "адресу". Необходимая для копирования область памяти уже должна быть выделена при помощи функций ALLOCMEM() или GETSPACE(). Если копируемая "строка" короче, нежели заданная "длина". то оставшаяся часть выделенной памяти заполняется значением "наполнителя" (по умолчанию - нулями).

Функция EXPORT() возвращает число скопированных байт. Адрес начала новой свободной области памяти может быть получен путем суммирования возвращенного значения и текущего адреса с помощью функции OFFSET().


FORBID()
res = FORBID()

Функция запрещает переключение задач в системе до исполнения парной ей функции PERMIT(). Возвращается счетчик вложения функций FORBID() (если переключение задач было разрешено на момент исполнения FORBID(), возвращается -1). Поскольку программы ARexx-a сами по себе являются отдельными задачами, в случае выхода из них в FORBID-состоянии ничего страшного не произойдет и многозадачный режим работы системы будет автоматически восстановлен. Эта функция используется при работе с различными системными списками для того, чтобы предотвратить обращение к ним из другой, одновременно работающей в системе задачи, в то время как текущая ARexx-программа просмотривает и/или модификацирует эти списки. Такая ситуация может привести к каким угодно неприятным последствиям. Между прочим, при исполнении информационной функции SHOWLIST() пара FORBID()-PERMIT() исполняется автоматически.

В FORBID-состоянии ввод-вывод с использованием средств ОС производить нельзя, поскольку системе придется ожидать окончания ввода/вывода другими задачами/процессами и для этого выйти из FORBID-coстояния.


FREEMEM()
res = FREEMEM(<адрес>,<длина>)

Функция освобождает системную память, резервированную ранее с помощью вызова ALLOCMEM(). Параметры "адрес" и "длина" должны быть теми же самыми, что и при вызове АLLОСМЕМ()!


FREESPACE()
res = FREESPACE(<адрес>,<длина>)

Функция освобождает системную память, резервированную ранее с помощью вызова GETSPACE(). Если параметры "адрес" и "длина" присутствуют, то они должны быть теми же самыми, что и при вызове GETSPACE()! При отсутствии параметров функция возвращает общий объем свободной памяти, находящейся в распоряжении ARexx-интерпретатора. При завершении программы вся память, резервированная с помощью GETSPACE(), будет освобождена и без явного исполнения FREESPACE().


GETSPACE()
res = GETSPACE(<длина>)

Функция резервирует блок памяти требуемой "длины" из памяти, находящейся в распоряжении интерпретатора. При завершении программы вся память, резервированная по GETSPACE() будет автоматически освобождена. В случае удачи возвращается адрес начала резервированного блока, в ином - нулевой адрес.


IMPORT()
res = IMPORT(<адрес>[,<длина>])

Функция возвращает строку требуемой "длины", начинающуюся с заданного "адреса". Если "длина" не указана, то строка копируется вплоть до первого встретившегося в ней нулевого байта.


NEXT()
res = NEXT(<адрес>[,<смещение>])

Возвращается новый адрес, равный сумме четырехбайтового значения, находящегося по "адресу", плюс значение "смещения". По сути, NEXT() является комбинацией функций IMPORT() и OFFSET(); целью является получение нового адреса, являющегося содержимым некоторой списочной структуры (как правило struct Node). Например, мы знаем, что системные списки содержат сначала адрес следующего узла (node), а после него идет адрес предыдущего узла. Допустим, "адрес" указывает на текущий узел. Тогда получить адреса предыдущего и последующего узлов проще простого:

PrevNode = NEXT(ThisNode, 4)
NextNode = NEXT(ThisNode)

Таким образом мы можем легко просканировать некоторый системный список. Базовый адрес почти всех ресурсов системы может быть получен с помощью функции SHOWLIST() с использованием четвертого аргумента "адрес".


NULL()
res = NULL()

Функция возвращает нулевой адрес в формате '0000 0000'х.


OFFSET()
res = OFFSET(<адрес>,<смещение>)

Функция возвращает новый адрес, являющийся суммой "адреса" и "смещения", которое должно являться десятичным числом со знаком. Использовать эту санкцию удобно для расчета адреса некоторого поля в структуре данных без обращения к функциям C2D() и D2C(), кроме того гарантируется, что возвращаемое значение будет четырехбайтовым адресом.


PERMIT()
res = PERMIT()

Функция уменьшает на единицу счетчик вложения вызовов FORBID() и возвращает текущее значение этого счетчика (напомним, что исходным значением счетчика является -1). Если после исполнения PERMIT() счетчик достигнет исходного значения, многозадачный режим работы системы, отключенный по FORBID(), будет включен снова.

Если ARexx-задача закончит работу в FORBID-состоянии, ничего страшного не произойдет, поскольку система в этом случае автоматически исполнит PERMIT().


STORAGE()
res = STORAGE([<адрес>[,<строка>][,<длина>][,<заполнитель>]])

Будучи использованной без аргументов, STORAGE() возвращает общий объем свободной памяти в системе. Если задан "адрес", то "строка" заданной "длины" будет скопирована по "адресу". Если строка короче заданной "длины", то оставшаяся часть будет заполнена байтом-"заполнителем" (по умолчанию - нулями).


Сайт создан в системе uCoz