Счетчик использования
Бывают случаи, когда при обработке множества объектов какого-либо типа данных необходимо использование определенного ресурса системы.
Примером подобной ситуации может служить необходимость протоколирования состояния различных объектов одного и того же типа в определенном файле, который специально для этого предназначен.
Для большей ясности, представим себе случай, когда тип данных описывает пользователя, получающего доступ к базе данных.
Объектов-пользователей базы данных может быть множество.
При этом, необходимо протоколировать действия каждого пользователя, осуществляемые при работе с базой данных, в едином файле протокола.
Подобная ситуация подразумевает, что при создании хотя бы одного объекта указанного типа данных, файл протокола состояний должен быть открыт.
Далее, при последующем создании объектов этого типа, открытие новых файлов для протоколирования состояний не выполняется.
При удалении не используемых объектов, файл протокола должен быть закрыт только тогда, когда удалены все объекты указанного типа данных.
Таким образом, нам необходимо осуществлять подсчет количества существующих объектов определенного типа данных, которые совместно используют ресурс системы.
Для решения таких задач удобно использовать контролируемые типы.
Рассмотрим следующий пример спецификации пакета:
with Ada.Text_IO; with Ada.Finalization; use Ada.Finalization;
package Log is type Item is private; procedure Put_To_Log (Self: in out Item; S: in String); private type Item is new Limited_Controlled with record . . . -- описание полей расширения end record; procedure Initialize (Self: in out Item); procedure Finalize (Self: in out Item); The_Log_File: Ada.Text_IO.File_Type; The_Counter: Natural := 0; end Log; |
Здесь тип Item описывает тип объектов при обработке которых используется общий файл протокола The_Log_File.
Для вывода информации о состоянии объекта типа Item в файл протокола The_Log_File
используется процедура Put_To_Log.
Для подсчета количества существующих в текущий момент объектов типа Item
используется переменная The_Counter.
Тело данного пакета может быть описано следующим образом:
package body Log is procedure Initialize (Self: in out Item) is begin The_Counter := The_Counter + 1; if The_Counter = 1 then Ada.Text_IO.Open (File => The_Log_File, Mode => Ada.Text_IO.Append_File, Name => "log.txt"); end if; end Initialize; procedure Finalize (Self: in out Item) is begin if The_Counter = 1 then Ada.Text_IO.Close (The_Log_File); end if; The_Counter := The_Counter - 1; end Finalize; procedure Put_To_Log (Self: in out Item; S: in String) is begin . . . -- вывод необходимых данных в файл The_Log_File end Put_To_Log; end Log; |
в переменной The_Counter
выполняется автоматически вызываемой процедурой Initialize.
Декремент количества существующих в текущий момент объектов типа Item
в переменной The_Counter и закрытие файла протокола The_Log_File
выполняется автоматически вызываемой процедурой Finalize.
Следует заметить, что при рассмотрении данного примера мы не заостряли внимание на структуре типа Item и реализации процедуры Put_To_Log, которая выводит информацию о состоянии объекта в файл протокола, поскольку в данном случае это не имеет принципиального значения.