русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Механизм подсчета ссылок

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

Подсчет ссылок на объект обеспечивают методы _AddRef и _Release интерфейса IInterface. При копировании значения интерфейсной переменной вызывается метод _AddRef, а при уничтожении интерфейсной переменной — метод _Release. Вызовы этих методов генерируются компилятором автоматически:

var Intf, Copy: IInterface;begin ... Copy := Intf; // Copy._Release; Intf._AddRef; Intf := nil; // Intf._Release; end; // Copy._Release

Стандартная реализация методов _AddRef и _Release находится в классе TInterfacedObject. Она достаточно проста и вы легко разберетесь с ней, читая комментарии в исходном тексте.

type TInterfacedObject = class(TObject, IInterface) ... FRefCount: Integer; // Счетчик ссылок function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; ... end; function TInterfacedObject._AddRef: Integer;begin Result := InterlockedIncrement(FRefCount); // Увеличение счетчика ссылокend; function TInterfacedObject._Release: Integer;begin Result := InterlockedDecrement(FRefCount); // Уменьшение счетчика ссылок if Result = 0 then // Если ссылок больше нет, то Destroy; // уничтожение объектаend;

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

Приведенную выше реализацию методов _AddRef и _Release автоматически получают все наследники класса TInterfacedObject, в том числе и классы TTextReader, TDelimitedReader и TFixedReader. Поэтому неиспользуемые объекты классов TDelimitedReader и TFixedReader тоже автоматически уничтожаются при работе с ними через интерфейсные переменные:

var Obj: TDelimitedReader; Intf, Copy: ITextReader;begin Obj := TDelimitedReader.Create('MyData.del', ';'); Intf := Obj; // Obj._AddRef -> Obj.FRefCount = 1 Copy := Intf; // Obj._AddRef -> Obj.FRefCount = 2 ... Intf := nil; // Obj._Release -> Obj.FRefCount = 1 Copy := nil; // Obj._Release -> Obj.FRefCount = 0 -> Obj.Destroy Obj.Free; // Ошибка! Объект уже уничтожен и переменная Obj указывает в никудаend;

Обратите внимание, что объектные переменные не учитываются при подсчете ссылок. Поэтому мы настоятельно рекомендуем избегать смешивания интерфейсных и объектных переменных. Если вы планируете использовать объект через интерфейс, то лучше всего результат работы конструктора сразу присвоить интерфейсной переменной:

var Intf: ITextReader;begin Intf := TDelimitedReader.Create('MyData.del', ';'); // FRefCount = 1 ... Intf := nil; // FRefCount = 0 -> Destroyend;

Если интерфейс является входным параметром подпрограммы, то при вызове подпрограммы создается копия интерфейсной переменной с вызовом метода _AddRef:

procedure LoadItems(R: ITextReader);begin...end; var Reader: ITextReader;begin ... LoadItems(Reader); // Создается копия переменной Reader и вызывается Reader._AddRefend;

Копия не создается, если входной параметр описан с ключевым словом const:

procedure LoadItems(const R: ITextReader);begin...end; var Reader: ITextRedaer;begin ... LoadItems(Reader); // Копия не создается, метод _AddRef не вызывается end;

Интерфейсная переменная уничтожается при выходе из области действия переменной, а это значит, что у нее автоматически вызывается метод _Release:

var Intf: ITextRedaer;begin Intf := TDelimitedReader.Create('MyData.del', ';'); ...end; // Intf._Release

Просмотров: 869


Вернуться в оглавление



Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.