Подтвердить что ты не робот

Как вы можете загрузить обернутый объект С++, если связанный объект Javascript - это мусор, собранный в V8?

Документация V8 объясняет как создать объект Javascript, который обертывает объект С++. Объект Javascript удерживает указатель на экземпляр объекта С++. Мой вопрос: скажем, вы создаете объект С++ в куче, как вы можете получить уведомление, когда объект Javascript будет собран gc, чтобы вы могли освободить кусок, выделенный для объекта С++?

4b9b3361

Ответ 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 не проверяет указатели на существование остроконечных объектов.