Документация V8 объясняет как создать объект Javascript, который обертывает объект С++. Объект Javascript удерживает указатель на экземпляр объекта С++. Мой вопрос: скажем, вы создаете объект С++ в куче, как вы можете получить уведомление, когда объект Javascript будет собран gc, чтобы вы могли освободить кусок, выделенный для объекта С++?
Как вы можете загрузить обернутый объект С++, если связанный объект Javascript - это мусор, собранный в V8?
Ответ 1
Трюк заключается в создании дескриптора Persistent
(вторая маркерная точка из ссылки на ссылку на API: "Persistent
дескрипторы не хранятся в стеке и удаляются только при их удалении. постоянный дескриптор, когда вам нужно поддерживать ссылку на объект более чем на один вызов функции или когда время жизни дескриптора не соответствует областям С++." ) и вызывать MakeWeak()
на нем, передавая функцию обратного вызова, которая будет выполнять необходимая очистка ( "Постоянный дескриптор может быть слабым, используя Persistent::MakeWeak
, чтобы вызвать обратный вызов от сборщика мусора, когда единственные ссылки на объект - из слабых постоянных дескрипторов".), то есть когда все "обычные" ручки вышли из сферы действия и когда сборщик мусора собирается удалить объект).
Подпись метода Persistent::MakeWeak
:
void MakeWeak(void* parameters, WeakReferenceCallback callback);
Где WeakReferenceCallback
определяется как указатель на функцию с двумя параметрами:
typedef void (*WeakReferenceCallback)(Persistent<Object> object,
void* parameter);
Они найдены в файле заголовка v8.h, распространяемом вместе с V8 как открытый API.
Вам нужна функция, которую вы передаете в MakeWeak
, чтобы очистить параметр объекта Persistent<Object>
, который будет передан ему, когда он будет вызван как обратный вызов. Параметр void* parameter
можно игнорировать (или void* parameter
может указывать на структуру С++, которая содержит объекты, которые требуют очистки):
void CleanupV8Point(Persistent<Object> object, void*)
{
// do whatever cleanup on object that you're looking for
object.destroyCppObjects();
}
Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());
// when the Javascript part of my_obj is about to be collected
// we'll have V8 call CleanupV8Point(my_obj)
my_obj.MakeWeak(NULL, &CleanupV8Point);
Ответ 2
В общем случае, если собранный мусором язык может содержать ссылки на ресурсы за пределами движка языка (файлы, сокеты или в ваших случаях на объектах С++), вы должны предоставить метод "закрыть", чтобы освободить этот ресурс ASAP, no пока GC не подумает, что стоит уничтожить ваш объект.
становится хуже, если ваш объект С++ голоден в памяти, а собранный мусором объект - это просто ссылка: вы можете выделить тысячи объектов, а GC видит только несколько килобайтных крошечных объектов, которых недостаточно для запуска коллекции; в то время как сторона С++ борется с десятками мегабайт устаревших объектов.
Ответ 3
Выполняйте всю свою работу в некоторой закрытой области (объекта или функции). Затем вы можете безопасно удалить объект С++, когда вы вышли из сферы действия. GC не проверяет указатели на существование остроконечных объектов.