热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

js引擎(v8)中实现一个多线程(进程)实例

v8是google开发的一个js引擎,其性能非常出色,包括Chrome在内的开源产品都在使用它,同时我们知道Chrome采用的是多进程模式,本文主要是例举一个基于v8的多进程JS编程API。

v8是google开发的一个js引擎,其性能非常出色,包括Chrome在内的开源产品都在使用它,同时我们知道Chrome采用的是多进程模式,本文主要是例举一个基于v8的多进程JS编程API。

#include <vector>
#include
"v8.h"

//读取js文件,返回js文件源码
v8::Handle<v8::String> ReadFile(const char* name)
{
FILE
* file = fopen(name, "rb");
if (file == NULL) return v8::Handle<v8::String>();
fseek(file,
0, SEEK_END);
int size = ftell(file);
rewind(file);
char* chars = new char[size + 1];
chars[size]
= '\0';
for (int i = 0; i < size;)
{
int read = fread(&chars[i], 1, size - i, file);
i
+= read;
}
fclose(file);
v8::Handle
<v8::String> result = v8::String::New(chars, size);
delete[] chars;
return result;
}

//执行js源代码,其中有编译和运行两个小步骤,并直接打印结果
void ExecuteString(const v8::Handle<v8::String> &source)
{
v8::HandleScope handle_scope;
v8::Handle
<v8::Script> script = v8::Script::Compile(source);

v8::Handle
<v8::Value> result = script->Run();
v8::String::Utf8Value str(result);
printf(
"%s\n", *str);
}


//////////////////////////////////////////


//线程模块,分为初始化和运行两个步骤
class Th : public v8::internal::Thread
{
public:
Th(
const char * js_func_name) : Thread("nameless")
{
strcpy(_fname,js_func_name);
}

virtual void Run()
{
Execute4Thread();
}
private:
void Execute4Thread()
{
v8::Isolate
* isolate = v8::Isolate::New();
v8::Isolate::Scope iscope(isolate);
v8::HandleScope scope;

v8::Persistent
<v8::Context> context = v8::Context::New();
v8::Context::Scope cscope(context);
run_proc();
context.Dispose();
}

void run_proc()
{
ExecuteString(ReadFile(_fname));
}

char _fname[20];
};

/////////////////////////////////////////


// 这个用于从js的参数中获取参数所属的c++对象,并返回对象指针
template<class T>
T
* get_cppobj_ptr(v8::Handle<v8::Object> obj)
{
v8::Handle
<v8::External> field = v8::Handle<v8::External>::Cast(obj->GetInternalField(0)) ;
void* raw_obj_ptr = field->Value() ;
return static_cast<T*>(raw_obj_ptr);
};


//暴露给js的c++对象,用于创建和运行线程
class Worker
{
public:
static v8::Handle<v8::Value> Start(const v8::Arguments & args)
{
Worker
* worker_ptr = get_cppobj_ptr<Worker>(args.Holder()) ;
worker_ptr
->StartWorker(args);
}

static v8::Handle<v8::Value> Join(const v8::Arguments & args)
{
Worker
* worker_ptr = get_cppobj_ptr<Worker>(args.Holder()) ;
worker_ptr
->JoinWorker(args);
}

inline
void StartWorker(const v8::Arguments & args)
{
for (int i = 0; i < args.Length(); i++)
{
v8::String::Utf8Value str(args[i]);
Th
*th = new Th(*str);
th
->Start();
ths_.push_back(th);
}
}

inline
void JoinWorker(const v8::Arguments & args)
{
std::vector
<Th*>::iterator it = ths_.begin();
for (; it!=ths_.end(); ++it)
{
(
*it)->Join();
}
}
private:
std::vector
<Th*> ths_;
};


//注册相关的c++对象到js环境中
void creat_obj(v8::Persistent<v8::Context> &exec_context)
{
v8::Handle
<v8::ObjectTemplate> foo_templ ;
v8::Handle
<v8::Object> foo_class_obj ;
v8::Handle
<v8::External> foo_class_ptr ;

Worker
* g_foo_ptr = new Worker;
foo_templ
= v8::ObjectTemplate::New();
foo_templ
->SetInternalFieldCount(1);
foo_class_obj
= foo_templ->NewInstance();

foo_class_ptr
= v8::External::New(static_cast<Worker *>(g_foo_ptr)) ;
foo_class_obj
->SetInternalField(0, foo_class_ptr) ;

foo_class_obj
->Set(v8::String::New("Start"),
v8::FunctionTemplate::New(Worker::Start)
->GetFunction()) ;

foo_class_obj
->Set(v8::String::New("Join"),
v8::FunctionTemplate::New(Worker::Join)
->GetFunction()) ;

exec_context
->Global()->Set(v8::String::New("Worker"),
foo_class_obj,
(v8::PropertyAttribute)(v8::ReadOnly)) ;
}



int main()
{
v8::HandleScope handle_scope;
v8::Persistent
<v8::Context> exec_context = v8::Context::New();
v8::Context::Scope context_scope(exec_context);
creat_obj(exec_context);

ExecuteString(ReadFile(
"test.js"));
return 0;
}

  

假设我们有三个js脚本文件:

// test.js 
Worker.Start('test1.js');
Worker.Start(
'test2.js');
Worker.Join();
'ok';


// test1.js
var str = 'test1';
for(i=0;i<=10000;i++)
str;



// test2.js
var str = 'test2';
str;

  

这边使用的是linux环境下,v8默认使用pthread库,通过静态编译以上的c++程序,

[root@hx test]# g++ -o test test.cpp  libv8.a -I/var/www/cpp/v8/src -lpthread -fno-rtti -fno-exceptions

[root@hx test]# ./test

test2

test1

ok

我们可以看到由于test1的运行时间比较长,故而后输出结果。


推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
author-avatar
摄影师张恒
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有