Bug 1343027 - 2. Add jni::Ref::Lock function; r=snorp

Add a Lock function to jni::Ref to lock the referenced object akin to
the synchronized keyword in Java. It returns an AutoLock RAII object
that automatically unlocks the object when going out of scope.
This commit is contained in:
Jim Chen 2017-03-06 15:32:36 -05:00
Родитель 0d3d8e6fd1
Коммит 3a24d6364c
2 изменённых файлов: 47 добавлений и 6 удалений

Просмотреть файл

@ -79,6 +79,45 @@ protected:
public: public:
using JNIType = Type; using JNIType = Type;
class AutoLock
{
friend class Ref<Cls, Type>;
JNIEnv* const mEnv;
Type mInstance;
AutoLock(Type aInstance)
: mEnv(FindEnv())
, mInstance(mEnv->NewLocalRef(aInstance))
{
mEnv->MonitorEnter(mInstance);
MOZ_CATCH_JNI_EXCEPTION(mEnv);
}
public:
AutoLock(AutoLock&& aOther)
: mEnv(aOther.mEnv)
, mInstance(aOther.mInstance)
{
aOther.mInstance = nullptr;
}
~AutoLock()
{
Unlock();
}
void Unlock()
{
if (mInstance) {
mEnv->MonitorExit(mInstance);
mEnv->DeleteLocalRef(mInstance);
MOZ_CATCH_JNI_EXCEPTION(mEnv);
mInstance = nullptr;
}
}
};
// Construct a Ref form a raw JNI reference. // Construct a Ref form a raw JNI reference.
static Ref<Cls, Type> From(JNIType obj) static Ref<Cls, Type> From(JNIType obj)
{ {
@ -117,6 +156,11 @@ public:
return T::Ref::From(*this); return T::Ref::From(*this);
} }
AutoLock Lock() const
{
return AutoLock(mInstance);
}
bool operator==(const Ref& other) const bool operator==(const Ref& other) const
{ {
// Treat two references of the same object as being the same. // Treat two references of the same object as being the same.

Просмотреть файл

@ -784,12 +784,9 @@ nsWindow::AndroidView::GetSettings(JSContext* aCx, JS::MutableHandleValue aOut)
return NS_OK; return NS_OK;
} }
JNIEnv* const env = jni::GetGeckoThreadEnv(); // Lock to prevent races with UI thread.
env->MonitorEnter(mSettings.Get()); auto lock = mSettings.Lock();
nsresult rv = widget::EventDispatcher::UnboxBundle(aCx, mSettings, aOut); return widget::EventDispatcher::UnboxBundle(aCx, mSettings, aOut);
env->MonitorExit(mSettings.Get());
return rv;
} }
/** /**