mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
0.9.1beta1: preliminary support for multi-threading.
This commit is contained in:
parent
05e4c5766f
commit
893cb16ddd
3 changed files with 36 additions and 1 deletions
|
@ -4,6 +4,10 @@
|
|||
|
||||
using namespace v8;
|
||||
|
||||
/**
|
||||
* Creates a new Persistent storage cell for `handle`
|
||||
* so that we can reference it from Ruby.
|
||||
*/
|
||||
v8_handle::v8_handle(Handle<void> handle) : handle(Persistent<void>::New(handle)) {
|
||||
this->weakref_callback = Qnil;
|
||||
this->weakref_callback_parameters = Qnil;
|
||||
|
@ -13,23 +17,50 @@ v8_handle::v8_handle(Handle<void> handle) : handle(Persistent<void>::New(handle)
|
|||
v8_handle::~v8_handle() {}
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Holds dead references, that are no longer being held in Ruby, so that they can be garbage collected
|
||||
* inside of V8
|
||||
*/
|
||||
VALUE handle_queue;
|
||||
|
||||
/**
|
||||
* Invoked by the Ruby garbage collector whenever it determines that this handle is
|
||||
* still reachable. We in turn, mark our weak callback parameters, so that it knows
|
||||
* they are reachable too.
|
||||
*/
|
||||
void v8_handle_mark(v8_handle* handle) {
|
||||
rb_gc_mark(handle->weakref_callback);
|
||||
rb_gc_mark(handle->weakref_callback_parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocates this handle. This function is invoked on Zombie handles after they have
|
||||
* been released from V8 and finally
|
||||
*/
|
||||
void v8_handle_free(v8_handle* handle) {
|
||||
delete handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whenver a V8::C::Handle becomes garbage collected, we do not free it immediately.
|
||||
* instead, we put them into a "zombie" queue, where its corresponding V8 storage cell
|
||||
* can be released safely while the V8 engine is running. A zombie Ruby object is
|
||||
* created to wrap it so that it can be stored in the queue.
|
||||
*/
|
||||
void v8_handle_enqueue(v8_handle* handle) {
|
||||
handle->dead = true;
|
||||
VALUE zombie = Data_Wrap_Struct(rr_v8_handle_class(), 0, v8_handle_free, handle);
|
||||
rb_ary_unshift(handle_queue, zombie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drains the dead handle queue, and releases them from V8
|
||||
*
|
||||
* This implements the V8 `GCPrologueCallback` and is registered to run before
|
||||
* each invocation of the V8 garbage collector. It empties the queue of dead handles
|
||||
* and disposes of them. It is important to do this operations inside V8 so that
|
||||
* Ruby garbage collection is never locked, and never touches V8.
|
||||
*/
|
||||
void v8_handle_dequeue(GCType type, GCCallbackFlags flags) {
|
||||
for (VALUE handle = rb_ary_pop(handle_queue); RTEST(handle); handle = rb_ary_pop(handle_queue)) {
|
||||
v8_handle* dead = NULL;
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#include <v8.h>
|
||||
#include "ruby.h"
|
||||
|
||||
/**
|
||||
* Holds a reference to a V8 heap object. This serves as the base
|
||||
* class for all of the low-level proxies that reference into V8
|
||||
*/
|
||||
struct v8_handle {
|
||||
v8_handle(v8::Handle<void> object);
|
||||
virtual ~v8_handle();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module V8
|
||||
VERSION = "0.9.0"
|
||||
VERSION = "0.9.1beta1"
|
||||
end
|
Loading…
Add table
Reference in a new issue