Справочное руководство по Ada 2012
13.11.4 Подпулы памяти
Этот подпункт определяет пакет для поддержки разбиения пула памяти на подпулы. Подпул может быть указан в качестве значения по умолчанию для выделения из связанного пула памяти, или конкретный подпул может быть указан в рамках аллокатора (см. 4.8).
Статическая семантика
Существует следующий определённый языком библиотечный пакет:
package System.Storage_Pools.Subpools is
pragma Preelaborate (Subpools);
pragma Preelaborate (Subpools);
type Root_Storage_Pool_With_Subpools is
abstract new Root_Storage_Pool with private;
abstract new Root_Storage_Pool with private;
type Root_Subpool is abstract tagged limited private;
type Subpool_Handle is access all Root_Subpool'Class;
for Subpool_Handle'Storage_Size use 0;
for Subpool_Handle'Storage_Size use 0;
function Create_Subpool (Pool : in out Root_Storage_Pool_With_Subpools)
return not null Subpool_Handle is abstract;
return not null Subpool_Handle is abstract;
-- Следующие операции предназначены для разработчиков пулов:
function Pool_of_Subpool (Subpool : not null Subpool_Handle)
return access Root_Storage_Pool_With_Subpools'Class;
return access Root_Storage_Pool_With_Subpools'Class;
procedure Set_Pool_of_Subpool (
Subpool : in not null Subpool_Handle;
To : in out Root_Storage_Pool_With_Subpools'Class);
Subpool : in not null Subpool_Handle;
To : in out Root_Storage_Pool_With_Subpools'Class);
procedure Allocate_From_Subpool (
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : out Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count;
Subpool : in not null Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : out Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count;
Subpool : in not null Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
procedure Deallocate_Subpool (
Pool : in out Root_Storage_Pool_With_Subpools;
Subpool : in out Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
Pool : in out Root_Storage_Pool_With_Subpools;
Subpool : in out Subpool_Handle) is abstract
with Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;
function Default_Subpool_for_Pool (
Pool : in out Root_Storage_Pool_With_Subpools)
return not null Subpool_Handle;
Pool : in out Root_Storage_Pool_With_Subpools)
return not null Subpool_Handle;
overriding
procedure Allocate (
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : out Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count);
procedure Allocate (
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : out Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count);
overriding
procedure Deallocate (
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : in Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count) is null;
procedure Deallocate (
Pool : in out Root_Storage_Pool_With_Subpools;
Storage_Address : in Address;
Size_In_Storage_Elements : in Storage_Elements.Storage_Count;
Alignment : in Storage_Elements.Storage_Count) is null;
overriding
function Storage_Size (Pool : Root_Storage_Pool_With_Subpools)
return Storage_Elements.Storage_Count
is (Storage_Elements.Storage_Count'Last);
function Storage_Size (Pool : Root_Storage_Pool_With_Subpools)
return Storage_Elements.Storage_Count
is (Storage_Elements.Storage_Count'Last);
private
... -- не определено языком
end System.Storage_Pools.Subpools;
... -- не определено языком
end System.Storage_Pools.Subpools;
Подпул — это обособлённая, подлежащая повторному освобождению часть пула памяти, идентифицируемая объектом типа Subpool_Handle (обработчик подпула). Обработчик подпула также идентифицирует окружающий пул памяти, пул памяти, поддерживающий подпулы, — это пул памяти, тип которого происходит от Root_Storage_Pool_With_Subpools. Подпул создаётся путём вызова Create_Subpool или аналогичного конструктора; конструктор возвращает обработчик подпула.
Объект подпула — это объект типа, происходящего от Root_Subpool. Как правило, объектами подпулов управляет содержащий пул памяти; только обработчики должны быть доступны клиентам пула памяти. Объекты подпулов обозначаются обработчиками подпулов и представляют собой рабочую реализацию подпула.
Каждый подпул принадлежит одному пулу памяти (который всегда будет пулом, поддерживающим подпулы). Доступ к пулу, которому принадлежит подпул, может быть получен путём вызова Pool_of_Subpool с обработчиком подпула. Set_Pool_of_Subpool заставляет подпул обработчика подпула принадлежать данному пулу; это предназначено для вызова из конструкторов подпула, таких как Create_Subpool. Set_Pool_of_Subpool распространяет Program_Error, если подпул уже принадлежит пулу. Если Set_Pool_of_Subpool ещё не был вызван для подпула, Pool_of_Subpool возвращает null.
При оценке аллокатора для типа, пул памяти которого поддерживает подпулы, вызывается Allocate_From_Subpool, передавая в него Subpool_Handle в дополнение к параметрам, определённым для вызовов Allocate (см. 13.11). Подпул, обозначенный именем subpool_handle_name, используется, если он указан в аллокаторе. В противном случае, для обеспечения обработчика подпула используется Default_Subpool_for_Pool пула. Все требования к процедуре Allocate также применяются к Allocate_from_Subpool.
Правила легальности
Если для типа доступа указан пул памяти, поддерживающий подпулы, тип доступа называется типом доступа к подпулу. Тип доступа к подпулу должен быть типом доступа, специфичным для пула.
Уровень доступа типа доступа к подпулу не должен быть статически глубже, чем у объекта пула памяти. Если указанный объект пула памяти является пулом памяти, поддерживающим подпулы, то имя, обозначающее объект, не должно обозначать часть формального параметра, а также не должно обозначать часть обращения к значению типа общего доступа, не относящегося к библиотечному уровню. В дополнение к местам, где обычно применяются правила легальности (см. 12.3), эти правила также применяются в частях с кодом `private` экземпляра порождённого модуля.
Динамическая семантика
Когда тип доступа со специфицированным пулом памяти замораживается (см. 13.14), если тег объекта пула памяти идентифицирует пул памяти, поддерживающий подпулы, производятся следующие проверки:
- имя, используемое для указания объекта пула памяти, не обозначает часть формального параметра, ни часть обращения к значению типа общего доступа, не относящегося к библиотечному уровню; и
- уровень доступа типа доступа не глубже, чем уровень доступа объекта пула памяти.
Program_Error поднимается, если какая-либо из этих проверок завершается неудачно.
Вызов Subpools.Allocate(P, Addr, Size, Align) выполняет следующее:
Allocate_From_Subpool
(Root_Storage_Pool_With_Subpools'Class(P),
Addr, Size, Align,
Subpool => Default_Subpool_for_Pool
(Root_Storage_Pool_With_Subpools'Class(P)));
(Root_Storage_Pool_With_Subpools'Class(P),
Addr, Size, Align,
Subpool => Default_Subpool_for_Pool
(Root_Storage_Pool_With_Subpools'Class(P)));
Аллокатор, который выделяет память в подпуле, вызывает Program_Error, если выделяемый объект содержит части задач.
Если Default_Subpool_for_Pool не переопределён, он поднимает Program_Error.
Ошибочное выполнение
Если Allocate_From_Subpool не удовлетворяет одному или нескольким требованиям к процедуре Allocate, как указано в правилах ошибочного выполнения из 13.11, тогда выполнение программы является ошибочным.
Разрешения реализации
При оценке аллокатора для типа, пул памяти которого имеет тип Root_Storage_Pool'Class, но поддерживает подпулы, реализация может вызвать Allocate вместо Allocate_From_Subpool. Это будет иметь тот же эффект, пока Allocate не будет переопределён.
ПРИМЕЧАНИЯ
33 Пользовательский тип пула памяти, поддерживающий подпулы, может быть реализован путём расширения типа Root_Storage_Pool_With_Subpools и переопределения примитивных подпрограмм Create_Subpool, Allocate_From_Subpool и Deallocate_Subpool. Create_Subpool должен вызвать Set_Pool_Of_Subpool перед возвращением обработчика подпула. Для использования такого пула пользователь должен объявить объект расширения типа, использовать его для определения атрибута Storage_Pool одного или нескольких типов доступа и затем вызвать Create_Subpool для получения обработчиков подпулов, связанных с пулом.
34 Пользовательский тип пула памяти, поддерживающий подпулы, может определить дополнительные конструкторы подпулов, аналогичные Create_Subpool (обычно они будут иметь дополнительные параметры).
35 Разработчик пула должен переопределить Default_Subpool_For_Pool, если пул должен поддерживать подпул по умолчанию. Разработчик может переопределить Deallocate, если необходимо поддерживать индивидуальное освобождение объектов, и может переопределить Storage_Size, если существует ограничение на общий размер пула памяти. Разработчик может переопределить Initialize и Finalize, если необходимы нетривиальные инициализация и завершение пула в целом. Например, Finalize может освободить блоки памяти, выделенные сверх пространства, занимаемого самим объектом пула. Разработчик пула может расширить тип Root_Subpool по мере необходимости, чтобы передавать дополнительную информацию с каждым подпулом, предоставляемым Create_Subpool.