Index: base/android/jni_method_id.h |
diff --git a/base/android/jni_method_id.h b/base/android/jni_method_id.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ca86d23b532659f67f18827255dda1a61e636db3 |
--- /dev/null |
+++ b/base/android/jni_method_id.h |
@@ -0,0 +1,81 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef BASE_ANDROID_JNI_METHOD_ID_ANDROID_H_ |
+#define BASE_ANDROID_JNI_METHOD_ID_ANDROID_H_ |
+ |
+#include <jni.h> |
+#include <sys/types.h> |
+ |
+#include "base/android/jni_android.h" |
+#include "base/atomicops.h" |
+#include "base/logging.h" |
+ |
+namespace base { |
+namespace android { |
+ |
+// This class is a wrapper for JNIEnv Get(Static)MethodID. |
joth
2012/10/03 17:31:52
call out this isn't a class at all, just a namespa
|
+// It's mostly used internally by the autogenerated JNI bindings. |
+class MethodID { |
+ public: |
+ enum MethodType { |
+ METHODTYPE_STATIC, |
+ METHODTYPE_NORMAL, |
+ }; |
+ |
+ // Wether or not to CHECK if an exception happens when |
+ // trying to obtain a method id. |
+ enum ExceptionCheck { |
+ EXCEPTIONCHECK_NO, |
+ EXCEPTIONCHECK_YES, |
+ }; |
+ |
+ template<MethodType method_type, |
+ ExceptionCheck exception_check> |
+ static jmethodID Get(JNIEnv* env, |
+ jclass clazz, |
+ const char* method_name, |
+ const char* jni_signature) { |
+ jmethodID id = method_type == METHODTYPE_STATIC ? |
+ env->GetStaticMethodID(clazz, method_name, jni_signature) : |
+ env->GetMethodID(clazz, method_name, jni_signature); |
+ if (exception_check == EXCEPTIONCHECK_YES) { |
+ CHECK(base::android::ClearException(env) || id) << |
+ "Failed to find " << |
+ (method_type == METHODTYPE_STATIC ? "static " : "") << |
+ "method " << method_name << " " << jni_signature; |
+ } else if (base::android::HasException(env)) { |
+ env->ExceptionClear(); |
+ } |
+ return id; |
joth
2012/10/03 17:31:52
I'd still prefer these method bodies into a .cc fi
|
+ } |
+ |
+ // The caller is responsible to zero-initialize |atomic_method_id|. |
+ // If it's set, it'll return immediately. Otherwise, it'll call into |
+ // ::Get() above. If there's a race, it's ok since the values are the same |
+ // (and the duplicated effort will happen only once). |
+ template<MethodType method_type, |
+ ExceptionCheck exception_check> |
+ static jmethodID LazyGet(JNIEnv* env, |
+ jclass clazz, |
+ const char* method_name, |
+ const char* jni_signature, |
+ base::subtle::AtomicWord* atomic_method_id) { |
+ COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jmethodID), |
+ AtomicWord_SmallerThan_jMethodID); |
+ subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_method_id); |
joth
2012/10/03 17:31:52
FWIW, I realized this doesn't need to be an 'acqui
|
+ if (value) |
+ return reinterpret_cast<jmethodID>(value); |
+ jmethodID id = MethodID::Get<method_type, exception_check>( |
+ env, clazz, method_name, jni_signature); |
+ base::subtle::Acquire_Store( |
joth
2012/10/03 17:31:52
nit: C++ style is to align params with open paren
|
+ atomic_method_id, reinterpret_cast<subtle::AtomicWord>(id)); |
+ return id; |
+ } |
+}; |
joth
2012/10/03 17:31:52
if you leave as a class, DISALLOW_IMPLICIT_CTOR an
|
+ |
+} // namespace android |
+} // namespace base |
+ |
+#endif // BASE_ANDROID_JNI_METHOD_ID_ANDROID_H_ |