2013-03-24 21 views
5

NDK kullanarak bir Android uygulamasında v8 gömmek çalışıyorum.v8 :: Locker'ı kullanmanın doğru yolu nedir ve neden kullanmalıyım?

ben bu (gösterilmemiştir JNI'yı haritalama kodu) gibi görünür JNI modülü vardır:

#include <jni.h> 
#include <android/log.h> 

#include <v8.h> 
using namespace v8; 

static jlong getMagicNumber() { 
    HandleScope handle_scope; 
    Persistent<Context> context = Context::New(); 
    Context::Scope context_scope(context); 

    Handle<String> source = String::New("40 + 2"); 

    Handle<Script> script = Script::Compile(source); 
    Handle<Value> result = script->Run(); 

    context.Dispose(); 

    return result->NumberValue(); 
} 

ben getMagicNumber ilk çalıştırdığınızda, doğru çalışır ve ben çalıştırmayı deneyin ikinci kez 42. döndürür o, çöker.

Özellikle, v8 en isolate.h görülen bu ASSERT başarısız: Bu "izolatı için özel erişim" elde etmek v8::Locker kullanarak önerir this problem gibi bir sürü sesler

// Returns the isolate inside which the current thread is running. 
INLINE(static Isolate* Current()) { 
    Isolate* isolate = reinterpret_cast<Isolate*>(
     Thread::GetExistingThreadLocal(isolate_key_)); 
    ASSERT(isolate != NULL); 
    return isolate; 
} 

.

getMagicNumber'un sonuna basit Locker l; ekleyerek, kilitlenme artık oluşmaz. Kendileriyle ilgilenen problemleri, dikkat etmediğimde kolaylıkla kırılma eğilimi gösterir.

Bu sorunun neden giderildiğini en çok anlayan anlayışa sahibim ve v8::Locker'u kullanımdan kaldırılmış bir şekilde kullanıyorum derleyici uyarıları alıyorum. Önerilen yöntem,'un yapıcısına bir argüman olarak v8::Isolate sağlamaktır, ancak bir izolatı nasıl elde edeceğimi bilmiyorum.

Sonuçta: Bu sorunu v8'in geçerli durumuna göre çözmek için uygun yol nedir ve neden?

cevap

6

Anladığım kadarıyla, bir V8 izolatı, bir yığın, çöp toplayıcı ve sıfır veya daha fazla V8 bağlamıyla birlikte V8 çalışma zamanının bir örneğidir. İzolatlar, diş güvenli olmayan 'dir ve v8::Locker aracılığıyla korunmalıdır. Sonra

v8::Isolate* isolate = v8::Isolate::New(); 

herhangi iplikten izolatı kullanmak: öncelikle bir izolatı oluşturmalısınız V8 Genelde

, kullanmak için bu noktada

v8::Locker locker(isolate); 
v8::Isolate::Scope isolateScope(isolate); 

iplik izolatı sahibi ve içerik oluşturmak, komut dosyalarını çalıştırmak ücretsizdir.

Şimdi, çok basit uygulamaların yararı için, V8 varsayılan bir izolat sağlar ve kilitleme gereksinimini rahatlatır. V8'e her zaman aynı iplikten erişirseniz, sadece bu koltuk değneklerini kullanabilirsiniz. Benim tahminim, ikinci arama farklı bir iş parçacığından yapıldığı için uygulamanız başarısız oldu.

+1

Hala bu satırların her birinin ne yaptığını anlamıyorum, ama bu benim için çalıştı. Teşekkürler. – namuol

0

Şimdi sadece V8 öğreniyorum ama sen aramak gerekir düşünüyorum:

v8 :: Locker soyunma (izole);

Bu, İzolatı başka bir iş parçacığı üzerinde kullanılmasını engelleyecek bir yığın ayrılmış Locker nesnesi oluşturacaktır. Geçerli fonksiyon döndüğünde, bu yığın nesnesinin imha cihazı otomatik olarak çağrılarak İzolatörün kilidinin açılması sağlanır.

aramak gerekir:

v8 :: İzole :: Kapsam isolateScope (izole);

Bu izolatı çalıştırmak için geçerli dizgiyi ayarlar. İzolatlar sadece bir iplik üzerinde kullanılabilir. Locker bunu zorlar, ancak İzolatörün kendisi, geçerli iş parçacığı için yapılandırılmalıdır. Bu, hangi yalıtmanın geçerli iş parçacığıyla ilişkili olduğunu belirten bir yığın ayrılmış nesne oluşturur. Tıpkı Locker gibi, bu değişken kapsam dışına çıktığında (geçerli işlev döndüğünde), Kapsam imha edici, İzolatı varsayılan olarak ayarlamak için çağrılır. Bunun gerekli olduğuna inanıyorum çünkü V8 API çağrılarının çoğunun bir İzolat'a bir referansa ihtiyacı vardır, ancak birini parametre olarak almayın. Bu nedenle doğrudan erişebilecekleri (muhtemelen her bir thread değişkenine göre) ihtiyaçları vardır.

Tüm Isolate :: Scope sınıfı yapıcıda isolate :: Enter() işlevini çağırır ve destructor'da iso :: Exit() öğesini ayırır. Bu nedenle daha fazla kontrol istiyorsanız, Enter()/Exit() öğesini çağırabilirsiniz.