首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何演示V8弱指针回调?

如何演示V8弱指针回调?
EN

Stack Overflow用户
提问于 2020-06-23 16:21:01
回答 1查看 332关注 0票数 0

我正在考虑使用V8作为一个项目的嵌入式JavaScript引擎,但我很难弄清楚如何管理本地C++对象的生存期。本实验旨在演示弱指针回调。

在下面代码的末尾,我调用v8::Persistent::SetWeak并安装一个回调。我想要的只是能够创建一个被调用的回调演示。

我半心半意地希望它会像让句柄超出作用域一样容易,但是下面的代码不会调用回调。我还在某个地方读到,调用Isolate::IdleNotificationDeadline可能会强制垃圾收集,但这也不起作用。

如何演示正在调用的弱指针回调?我想编写一些代码,以便在程序退出之前的某个时候调用cleanup函数。

显然,我很难理解如何正确地设置这个问题,并希望得到一些帮助和解释。恐怕我还不明白。

我的期望是,可以通过Persistent句柄创建弱指针,并且当对象没有句柄时,回调(最终)将被调用,以便释放与该JavaScript对象关联的本地C++资源。

v8.h头文件中的注释尤其让我感到不快:

注意:无法保证何时或是否调用回调。调用只在最大努力的基础上执行。与以往一样,基于GC的终结不应被依赖于任何关键形式的资源管理!

这使得整个引擎对于使用这种机制管理本机对象似乎毫无用处。但我确信至少有一些最小的人为场景,其中调用回调。

我的要求是,我能够编写一些JavaScript来分配一个对象,当没有对它的引用时,该对象最终将被释放。

代码语言:javascript
复制
foo = createFoo(); // creates a JavaScript object wrapping the native C++ Foo object.
doSomethingWith(foo); // do stuff with the Foo here
foo = null; // make sure there are no more JavaScript handles to the wrapper for the Foo object.
// After this point, I'm hoping V8 will eventually let me know that I can delete the native C++ Foo object

我假设我实际上不需要执行任何JavaScript来演示弱指针和清理机制。我希望我可以创建一个Persistent句柄,然后安装弱回调,然后让它超出范围。我的假设似乎是错误的,或者我没有在这里证明这一点。

代码语言:javascript
复制
#include <iostream>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"

class Foo {};

void cleanup(const v8::WeakCallbackInfo<Foo>& data)
{
  std::cout << "Weak Callback called" << std::endl;
  delete data.GetParameter();
}

int main(int argc, char* argv[]) {
  std::cout << "Start..." << std::endl;

  v8::V8::InitializeICUDefaultLocation(argv[0]);
  v8::V8::InitializeExternalStartupData(argv[0]);
  std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
  v8::V8::InitializePlatform(platform.get());
  v8::V8::Initialize();

  // Create a new isolate and make it the current one
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
  v8::Isolate* isolate = v8::Isolate::New(create_params);

  {
    v8::Isolate::Scope isolate_scope(isolate);
    v8::HandleScope handle_scope(isolate);

    v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, v8::ObjectTemplate::New(isolate));
    v8::Context::Scope context_scope(context);

    v8::Local<v8::Object> obj = v8::ObjectTemplate::New(isolate)->NewInstance(context).ToLocalChecked();
    v8::Persistent<v8::Object> persistent;
    persistent.Reset(isolate, obj);
    persistent.SetWeak(new Foo(), cleanup, v8::WeakCallbackType::kParameter);
  }

  isolate->IdleNotificationDeadline(1.0);

  std::cout << "...Finish" << std::endl;
}

注意:上面的代码示例应该按照构建了V8的世界示例的方式构建。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-23 20:09:37

对于一个精心设计的例子,调用isolate->LowMemoryNotification()应该可以做到这一点。不过,我不建议在生产中这样做,因为这是对CPU时间的巨大浪费(除非您的内存状况确实很低,因为OOM差点崩溃)。

除此之外,你发现的评论也成立。依赖对空闲对象的弱回调很好;不建议依赖它来管理关键和稀缺的资源。如果有问题的对象加起来很大,那么您应该酌情使用isolate->AdjustAmountOfExternalAllocatedMemory(...),让GC知道有什么东西需要释放。而且,您应该有自己的后备机制,以便在Isolate消失时清理所有东西(如果您没有终止整个进程,那么无论如何)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62539339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档