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

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的运行时间比较长,故而后输出结果。

posted @ 2011-08-16 20:30  lajabs  阅读(6003)  评论(1编辑  收藏  举报