1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

Add Locker and Unlocker

This commit is contained in:
Georgy Angelov 2015-03-21 20:27:06 +00:00
parent 143bbb1232
commit 207158fcdb
6 changed files with 164 additions and 16 deletions

View file

@ -17,7 +17,8 @@ extern "C" {
Object::Init();
Primitive::Init();
String::Init();
// v8::Locker lock();
Locker::Init();
// GC::Init();
// Accessor::Init();
// Invocation::Init();
@ -34,7 +35,6 @@ extern "C" {
// Message::Init();
// TryCatch::Init();
// Exception::Init();
// Locker::Init();
// ResourceConstraints::Init();
// HeapStatistics::Init();
}

83
ext/v8/locker.cc Normal file
View file

@ -0,0 +1,83 @@
#include "rr.h"
namespace rr {
void Locker::Init() {
ClassBuilder("Locker").
defineSingletonMethod("IsLocked", &IsLocked).
defineSingletonMethod("IsActive", &IsActive);
VALUE v8 = rb_define_module("V8");
VALUE c = rb_define_module_under(v8, "C");
rb_define_singleton_method(c, "Locker", (VALUE (*)(...))&Lock, -1);
rb_define_singleton_method(c, "Unlocker",(VALUE (*)(...))&Unlock, -1);
}
VALUE Locker::IsLocked(VALUE self, VALUE isolate) {
return Bool(v8::Locker::IsLocked(Isolate(isolate)));
}
VALUE Locker::IsActive(VALUE self) {
return Bool(v8::Locker::IsActive());
}
VALUE Locker::Lock(int argc, VALUE* argv, VALUE self) {
if (!rb_block_given_p()) {
return Qnil;
}
int state = 0;
VALUE isolate, block;
rb_scan_args(argc, argv, "10&", &isolate, &block);
VALUE result = setupLockAndCall(Isolate(isolate), &state, block);
if (state != 0) {
rb_jump_tag(state);
}
return result;
}
VALUE Locker::setupLockAndCall(Isolate isolate, int* state, VALUE block) {
v8::Locker locker(isolate);
return rb_protect(&doLockCall, block, state);
}
VALUE Locker::doLockCall(VALUE block) {
return rb_funcall(block, rb_intern("call"), 0);
}
VALUE Locker::Unlock(int argc, VALUE* argv, VALUE self) {
if (!rb_block_given_p()) {
return Qnil;
}
int state = 0;
VALUE isolate, block;
rb_scan_args(argc, argv, "10&", &isolate, &block);
VALUE result = setupUnlockAndCall(Isolate(isolate), &state, block);
if (state != 0) {
rb_jump_tag(state);
}
return result;
}
VALUE Locker::setupUnlockAndCall(Isolate isolate, int* state, VALUE block) {
v8::Unlocker unlocker(isolate);
return rb_protect(&doUnlockCall, block, state);
}
VALUE Locker::doUnlockCall(VALUE block) {
return rb_funcall(block, rb_intern("call"), 0);
}
}

26
ext/v8/locker.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef RR_LOCKER
#define RR_LOCKER
namespace rr {
class Locker {
public:
static void Init();
static VALUE IsLocked(VALUE self, VALUE isolate);
static VALUE IsActive(VALUE self);
static VALUE Lock(int argc, VALUE* argv, VALUE self);
static VALUE Unlock(int argc, VALUE* argv, VALUE self);
protected:
static VALUE setupLockAndCall(Isolate isolate, int* state, VALUE code);
static VALUE doLockCall(VALUE code);
static VALUE setupUnlockAndCall(Isolate isolate, int* state, VALUE code);
static VALUE doUnlockCall(VALUE code);
};
}
#endif

View file

@ -19,6 +19,7 @@
#include "v8.h"
#include "isolate.h"
#include "locker.h"
#include "handles.h"
#include "context.h"

41
spec/c/locker_spec.rb Normal file
View file

@ -0,0 +1,41 @@
require 'c_spec_helper'
describe V8::C::Locker do
let(:isolate) { V8::C::Isolate.New }
it 'can lock and unlock the VM' do
expect(V8::C::Locker::IsLocked(isolate)).to eq false
V8::C::Locker(isolate) do
expect(V8::C::Locker::IsLocked(isolate)).to eq true
V8::C::Unlocker(isolate) do
expect(V8::C::Locker::IsLocked(isolate)).to eq false
end
end
expect(V8::C::Locker::IsLocked(isolate)).to eq false
end
it 'properly unlocks if an exception is thrown inside a lock block' do
begin
V8::C::Locker(isolate) do
raise 'boom!'
end
rescue
expect(V8::C::Locker::IsLocked(isolate)).to eq false
end
end
it 'properly re-locks if an exception is thrown inside an un-lock block' do
V8::C::Locker(isolate) do
begin
V8::C::Unlocker(isolate) do
raise 'boom!'
end
rescue
expect(V8::C::Locker::IsLocked(isolate)).to eq true
end
end
end
end

View file

@ -11,24 +11,21 @@ module V8ContextHelpers
end
def bootstrap_v8_context
cleanup_isolates
isolate = V8::C::Isolate.New
begin
cleanup_isolates
V8::C::Locker(isolate) do
isolate.Enter
# V8::C::Locker() do
V8::C::HandleScope(isolate) do
@cxt = V8::C::Context::New(isolate)
begin
@cxt.Enter
yield
ensure
@cxt.Exit
end
V8::C::HandleScope(isolate) do
@cxt = V8::C::Context::New(isolate)
begin
@cxt.Enter
yield
ensure
@cxt.Exit
end
# end
ensure
end
isolate.Exit
end
end