Поделиться через


Реализация подсчета ссылок

Подсчет ссылок требует работы как со стороны инициатора класса, так и клиентов, использующих объекты этого класса. При реализации класса необходимо реализовать методы AddRef и Release в рамках интерфейса IUnknown. Эти два метода имеют следующие простые реализации:

  • AddRef увеличивает количество внутренних ссылок объекта.
  • освобождение сначала уменьшает внутренний счётчик ссылок объекта, а затем проверяет, упало ли число ссылок до нуля. Если это так, это означает, что никто не использует объект, поэтому функция Release освобождает объект.

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

Каждый раз, когда клиент вызывает метод (или функцию API), например QueryInterface, который возвращает новый указатель интерфейса, вызываемый метод отвечает за увеличение количества ссылок через возвращаемый указатель. Например, когда клиент впервые создает объект, он получает указатель интерфейса на объект, который, с точки зрения клиента, имеет количество ссылок, равное одному. Если клиент вызывает AddRef на указателе интерфейса, число ссылок становится двумя. Клиент должен дважды вызвать Release на указателе интерфейса, чтобы удалить все ссылки на объект.

Пример того, как счетчики ссылок строго зависят от указателя интерфейса, возникает, когда клиент вызывает QueryInterface на первом указателе, независимо от того, будет ли это новый интерфейс или тот же интерфейс. В любом из этих случаев клиент должен вызывать выпуск один раз для каждого указателя. COM не требует, чтобы объект возвращал один и тот же указатель при запросе одного и того же интерфейса несколько раз. (Единственным исключением является запрос на IUnknown, который определяет объект в COM.) Это позволяет реализации объекта эффективно управлять ресурсами.

Безопасность потоков также является важной проблемой при реализации AddRef и Release. Дополнительные сведения см. в Процессах, Потоках и Апартаментах.

управление временем существования объектов с помощью подсчета ссылок