2010-08-06 11:24:01 -04:00
|
|
|
#include "rr.h"
|
|
|
|
#include "v8_locker.h"
|
|
|
|
|
|
|
|
using namespace v8;
|
|
|
|
|
|
|
|
namespace {
|
2011-06-11 16:22:14 -04:00
|
|
|
namespace Lock {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#new
|
|
|
|
*
|
|
|
|
* Allocates and returns a new `v8::Locker` object. The thread that instantiated
|
|
|
|
* this object will hold the V8 interpreter lock until it is released with a
|
|
|
|
* corresponding call to {#delete}.
|
|
|
|
*
|
|
|
|
* It critical that you call {#delete} to deallocate it, preferably within the same method.
|
|
|
|
* If you don't, two bad things will happen:
|
|
|
|
*
|
|
|
|
* 1. You'll leak the underlying C++ object
|
|
|
|
* 1. Worse, you'll leave the V8 vm locked to this thread forever
|
|
|
|
*
|
|
|
|
* It's dangerous! Be sure to `ensure`.
|
|
|
|
*
|
|
|
|
* for detailed semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
|
|
|
|
*
|
|
|
|
* @return [V8::C::Locker] the new locker
|
|
|
|
*/
|
|
|
|
|
|
|
|
VALUE New(VALUE LockerClass) {
|
|
|
|
Locker* locker = new Locker();
|
|
|
|
return Data_Wrap_Struct(LockerClass, 0, 0, (void*)locker);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#delete
|
|
|
|
*
|
|
|
|
* Pop this lock off the stack for this thread. For a full run down of V8 locking
|
|
|
|
* semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
|
|
|
|
* @return nil
|
|
|
|
*/
|
|
|
|
VALUE Delete(VALUE self) {
|
|
|
|
Locker* locker = 0;
|
|
|
|
Data_Get_Struct(self, class Locker, locker);
|
|
|
|
delete locker;
|
|
|
|
}
|
2010-08-06 11:24:01 -04:00
|
|
|
}
|
2011-06-11 16:22:14 -04:00
|
|
|
|
|
|
|
namespace Unlock {
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Unlocker#new
|
|
|
|
*
|
|
|
|
* Allocates and returns a new `v8::UnLocker` object, temporarily releasing any locks that
|
|
|
|
* this thread is holding. It will reaquire all of the locksto {#delete}.
|
|
|
|
*
|
|
|
|
* This is a great thing to do when you want to call out to some code that might do some
|
|
|
|
* waiting, sleeping, and you want to politely let other threads use this VM.
|
|
|
|
*
|
|
|
|
* It critical that you call {#delete} to deallocate it, preferably within the same method.
|
|
|
|
* If you don't, two bad things will happen:
|
|
|
|
*
|
|
|
|
* 1. You'll leak the underlying C++ object
|
|
|
|
* 1. You won't restore the locks to your current thread, and will mess things up horribly
|
|
|
|
*
|
|
|
|
* It's dangerous! Be sure to `ensure`.
|
|
|
|
*
|
|
|
|
* For details on V8 locking semantics, see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
|
|
|
|
* @return [V8::C::Unocker] the new locker
|
|
|
|
*/
|
|
|
|
VALUE New(VALUE UnockerClass) {
|
|
|
|
Unlocker unlocker = new Unlocker();
|
|
|
|
return Data_Wrap_Struct(UnlockerClass, 0, 0, (void*)unlocker);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Unlocker#delete
|
|
|
|
*
|
|
|
|
* Restore any locks to the stack that were temporarily removed by this `Unlocker`.
|
|
|
|
* For a full run down, see semantics see the locking {API http://izs.me/v8-docs/classv8_1_1Unlocker.html}
|
|
|
|
* @return nil
|
|
|
|
*/
|
|
|
|
VALUE Delete(VALUE self) {
|
|
|
|
Unlocker* unlocker;
|
|
|
|
Data_Get_Struct(self, class Locker, locker);
|
|
|
|
delete unlocker;
|
|
|
|
}
|
2010-08-06 11:24:01 -04:00
|
|
|
}
|
2011-06-11 16:22:14 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#StartPreemption
|
|
|
|
* Start preemption.
|
|
|
|
* When preemption is started, a timer is fired every n milli seconds that will switch between
|
|
|
|
* multiple threads that are in contention for the V8 lock.
|
|
|
|
*
|
|
|
|
* @param [Integer] every_n_ms
|
|
|
|
* @return nil
|
|
|
|
*/
|
|
|
|
VALUE StartPreemption(VALUE self, VALUE every_n_ms) {
|
|
|
|
Locker::StartPreemption(NUM2INT(rb_to_int(every_n_ms)));
|
2010-08-06 11:24:01 -04:00
|
|
|
return Qnil;
|
|
|
|
}
|
2011-06-11 16:22:14 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#StartPreemption
|
|
|
|
* Stop preemption
|
|
|
|
*/
|
2010-08-06 11:24:01 -04:00
|
|
|
VALUE StopPreemption(VALUE self) {
|
|
|
|
Locker::StopPreemption();
|
|
|
|
return Qnil;
|
|
|
|
}
|
2011-06-11 16:22:14 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#IsLocked
|
|
|
|
* Returns whether or not the locker is locked by the current thread.
|
|
|
|
*/
|
2010-08-06 11:24:01 -04:00
|
|
|
VALUE IsLocked(VALUE self) {
|
|
|
|
return rr_v82rb(Locker::IsLocked());
|
|
|
|
}
|
2011-06-11 16:22:14 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Document-method: V8::C::Locker#IsActive
|
|
|
|
* Returns whether v8::Locker is being used by this V8 instance.
|
|
|
|
*/
|
2010-08-06 11:24:01 -04:00
|
|
|
VALUE IsActive(VALUE self) {
|
|
|
|
return rr_v82rb(Locker::IsActive());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void rr_init_v8_locker() {
|
|
|
|
VALUE V8 = rb_define_module("V8");
|
2011-06-11 16:22:14 -04:00
|
|
|
VALUE LockerClass = rr_define_class("Locker");
|
|
|
|
VALUE UnlockerClass = rr_define_class("Unlocker");
|
|
|
|
rr_define_singleton_method(LockerClass, "new", Lock::New, 0);
|
|
|
|
rr_define_method(LockerClass, "delete", Lock::Delete, 0);
|
|
|
|
rr_define_singleton_method(UnlockerClass, "new", Unlock::New, 0);
|
|
|
|
rr_define_method(UnlockerClass, "delete", Unlock::Delete, 0);
|
|
|
|
rr_define_singleton_method(LockerClass, "StartPreemption", StartPreemption, 1);
|
|
|
|
rr_define_singleton_method(LockerClass, "StopPreemption", StopPreemption, 0);
|
|
|
|
rr_define_singleton_method(LockerClass, "IsLocked", IsLocked, 0);
|
|
|
|
rr_define_singleton_method(LockerClass, "IsActive", IsActive, 0);
|
2010-08-06 11:24:01 -04:00
|
|
|
}
|