Главная » Haskell » Модуль Weak

0

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

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

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

Использование модуля:

import System.Mem.Weak

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

Тип: Weak

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

data  Weak  a = …

Тип определён в виде примитива.

Слабые указатели могут иметь финализаторы. Если финализатор существует, то есть гарантия, что он будет запущен по крайней мере один раз тогда, когда ключ станет недоступным в программе. Система управления памятью будет стараться запустить финализатор сразу  же,  как только ключ умрёт, однако сама по себе  оперативность  запуска не гарантируется. Также  не гарантируется то, что финализатор будет вообще запущен, поскольку финализаторы выполняются при выходе из программы. Поэтому финализаторы не должны использоваться в целях высвобождения памяти, для этих целей необходимо пользоваться другими средствами, в частности генерацией и отловом исключений.

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

Для данного типа определён экземпляр класса Typeable1.

Функция: mkWeak

Описание: создаёт слабый указатель на первый аргумент со значением второго аргумента и с третьим аргументом в качестве финализатора (может отсутствовать). Эта функция является наиболее общим способом создания слабых указателей.

Определение:

mkWeak  :: k  ->  v  ->  Maybe (IO  ()) ->  IO (Weak v)

Функция определена в виде примитива.

Функция: mkWeakPtr

Описание: специализированная версия функции mkWeak, в которой ключ и значение являются одним и тем же объектом.

Определение:

mkWeakPtr  :: k  ->  Maybe (IO  ()) ->  IO  (Weak k) mkWeakPtr  key  finalizer =  mkWeak  key  key  finalizer

Функция: mkWeakPair

Описание: вариант функции mkWeak, который в качестве значения слабого указателя создаёт пару вида (ключ, значение).

Определение:

mkWeakPair  :: k  ->  v  ->  Maybe (IO  ()) ->  IO (Weak  (k, v)) mkWeakPair  key  val   finalizer = mkWeak  key  (key, val) finalizer

Функция: deRefWeak

Описание: возвращает значение из слабого указателя. Если значение ещё существует, оно возвращается в конструкторе Just. Если значения уже нет, возвращается Nothing. Значение обёрнуто в монаду IO, поскольку оно зависит от процесса сборки мусора, а потому недетерминировано.

Определение:

deRefWeak  :: Weak  v  ->  IO (Maybe v)

Функция определена в виде примитива.

Функция: finalize

Описание: запускает финализатор, ассоциированный со слабым указателем.

Определение:

finalize ::  Weak  v  ->  IO ()

Функция определена в виде примитива.

Функция: addFinalizer

Описание: добавляет финализатор к заданному слабому указателю.

Определение:

addFinalizer :: key  ->  IO () ->  IO ()

addFinalizer key  finalizer = do mkWeakPtr  key  (Just  finalizer) return ()

Источник: Душкин Р. В., Справочник по языку Haskell. М.: ДМК Пресс, 2008. 544 с., ил.

По теме:

  • Комментарии