Я пытаюсь расширить язык Clojure, чтобы расширить ACI-гарантированные ссылки на ACID-гарантированные ссылки (длительные ссылки).API должен просто вызывать (dref key value)
, где key
- это строка ключа, который будет использоваться в базовом хранилище данных (BDB JE в моей текущей реализации), а value
- это объект, которым должен быть dref.инициализирован до.Если key
уже существует в БД, вместо него используется сохраненное значение.
Можно создать несколько dref с одним и тем же ключом, и их необходимо синхронизировать, т. Е. Если участвует один dref с ключом "A"в транзакции, где она записывается или читается с (ensure)
, все другие dref с ключом «A» должны быть синхронизированы с транзакцией: блокировки чтения и блокировки записи должны использоваться для наложения порядка на транзакции, включающие эти drefs.В более широком смысле, хотя в одном и том же ключе может быть несколько dref в памяти, все эти dref с этим ключом являются одним логическим объектом.
По очевидным причинам гораздо проще просточто этот единственный логический dref реализован с одним конкретным dref в памяти.Таким образом, нечего синхронизировать.Как мне это сделать?
Очевидный ответ - использовать пул объектов с ключом key .Затем Clojure вызовет статический метод getInstance(key,value)
для извлечения из пула, если он существует, и создаст его и заполнит пул, если нет.Проблема с этим подходом состоит в том, что нет простого способа заставить Clojure выпустить объект, когда это будет сделано.Город утечки памяти.Я должен убедиться, что любой объект с сильными ссылками на него не будет собран и что они существуют в пуле.Было бы катастрофично, если пул потерял бы ссылки на логические dref, которые все еще используются, так как другой процесс мог бы создать новый dref с тем же ключом, и он не был бы безопасен в транзакционном отношении с другим dref с тем же ключом.
Так что мне нужна какая-то версия WeakHashMap
или что-то с использованием не сильных ссылок (я бы предпочел SoftReference
s для немного большего нежелания со стороны GC).Итак:
- Если я использую
HashMap<String,SoftReference<DRef>>
, как я могу гарантировать, что на карте будут удалены записи, если будет собрано значение записи (SoftReference)?Какой-то поток демона? - Как сделать потокобезопасным пул для GC?Или мне не нужно беспокоиться об этом, поскольку сборщик мусора работает на уровне
SoftReference
, а мой поток демона будет работать на уровне Map
? - Что касается связанных примечаний, как мне это сделать?убедиться, что поток демона запущен?Есть ли способ, которым он может остановиться, не выдав исключение, которое приведет к аварийному завершению всего JVM, если он не будет обработан?Если так, как я могу контролировать и при необходимости запустить новый?