сборка мусора данных обработчика вызовов

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

Если я закомментирую строку, содержащую «tpl->SetCallHandler(callFn, external);» ObjWeakCallback называется. Функция никогда не собирается, хотя (по крайней мере, FnWeakCallback никогда не называется, несмотря ни на что).

Обратите внимание, что статические данные не являются опцией, так как они должны быть готовы к нескольким изолятам на процесс.
isolate->setData это тоже не вариант. Я что-то упустил полностью?
Как правильно хранить данные внутри v8::Function, есть ли?


редактировать: Позвольте мне перефразировать вопрос, чтобы лучше описать мое намерение …

Я хотел бы создать шаблон функции (потому что мне нужно использовать его в качестве конструктора на стороне JS).
Мне нужен какой-то способ отправить void * в его обработчик вызовов, но эти данные должны быть сборщиками мусора.

Несколько заметок о том, что я пробовал до сих пор:

  • с помощью Function::New(isolate, callHandler, External::New(isolate, data)) работает, но не предоставляет возможности конструктора на стороне JS (невозможно для SetInternalFieldCount для созданного объекта)

  • FunctionTemplate::New(isolate, callHandler, External::New(isolate, data)) предоставляет возможность передавать данные в обработчик вызовов, но никогда не собирает мусор (<не> рабочий пример ниже)

  • Я попытался использовать обычную функцию и вернуть только что созданный Object, но тогда следующее предположение new Fn() instanceof Fn терпит неудачу


#include <v8.h>
#include <iostream>

// made static, just to simplify the example and prevent crashes
// the persistents would normally be wrapped inside a "baton" together with required data
v8::Persistent<v8::Value> p_obj;
v8::Persistent<v8::Value> p_fn;

void FnWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) {
int* number = data.GetParameter();
std::cout << "GC fn " << number << '\n';
delete number;
p_fn.Reset();
}

void ObjWeakCallback(const v8::WeakCallbackData<v8::Value, int>& data) {
int* number = data.GetParameter();
std::cout << "GC obj " << number << '\n';
delete number;
p_obj.Reset();
}

void callFn(const v8::FunctionCallbackInfo<v8::Value>& info) {
std::cout << "called\n";
}

void test(v8::Isolate* isolate) {
v8::HandleScope scope(isolate);

auto external = v8::External::New(isolate, new int{ 1 });
p_obj.Reset(isolate, external);
p_obj.SetWeak(new int{ 1 }, ObjWeakCallback);

auto tpl = v8::FunctionTemplate::New(isolate);
tpl->SetCallHandler(callFn, external); // <======
tpl->InstanceTemplate()->SetInternalFieldCount(1);
auto fn = tpl->GetFunction();

p_fn.Reset(isolate, fn);
p_fn.SetWeak(new int{ 2 }, FnWeakCallback);
}

int main() {
v8::V8::SetFlagsFromString("--expose-gc", 11);

auto isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
auto context = v8::Context::New(isolate);
context->Enter();

test(isolate);

isolate->RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection);
context->Exit();

return 0;
}

2

Решение

Теперь я обманул и посмотрел на код

void GCController::CollectAll(const gin::Arguments& args) {
// In order to collect a DOM wrapper, two GC cycles are needed.
// In the first GC cycle, a weak callback of the DOM wrapper is called back
// and the weak callback disposes a persistent handle to the DOM wrapper.
// In the second GC cycle, the DOM wrapper is reclaimed.
// Given that two GC cycles are needed to collect one DOM wrapper,
// more than two GC cycles are needed to collect all DOM wrappers
// that are chained. Seven GC cycles look enough in most tests.

Таким образом, ответ должен быть: вы не увидите ничего после первого сбора.

1

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector