Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: base/android/jni_android.cc

Issue 8769005: Don't use Singleton to cache JNI method IDs in Java Bridge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated comments, share some constants Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/android/jni_android.h" 5 #include "base/android/jni_android.h"
6 6
7 #include <map>
8
7 #include "base/android/scoped_java_ref.h" 9 #include "base/android/scoped_java_ref.h"
10 #include "base/atomicops.h"
11 #include "base/lazy_instance.h"
8 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/threading/platform_thread.h"
9 14
10 namespace { 15 namespace {
11 JavaVM* g_jvm = 0; 16 JavaVM* g_jvm = 0;
12 jobject g_application_context = NULL; 17 jobject g_application_context = NULL;
18
19 typedef std::map<std::string, jmethodID> MethodIDMap;
20 base::LazyInstance<MethodIDMap> g_method_id_map = LAZY_INSTANCE_INITIALIZER;
joth 2011/12/02 14:10:13 fwiw, I think we're happy to use LeakyLazyInstance
21 const base::subtle::AtomicWord kUnlocked = 0;
22 const base::subtle::AtomicWord kLocked = 1;
23 base::subtle::AtomicWord g_method_id_map_lock = kUnlocked;
13 } 24 }
14 25
15 namespace base { 26 namespace base {
16 namespace android { 27 namespace android {
17 28
18 JNIEnv* AttachCurrentThread() { 29 JNIEnv* AttachCurrentThread() {
19 if (!g_jvm) 30 if (!g_jvm)
20 return NULL; 31 return NULL;
21 32
22 JNIEnv* env = NULL; 33 JNIEnv* env = NULL;
(...skipping 17 matching lines...) Expand all
40 void InitApplicationContext(jobject context) { 51 void InitApplicationContext(jobject context) {
41 DCHECK(!g_application_context); 52 DCHECK(!g_application_context);
42 g_application_context = context; 53 g_application_context = context;
43 } 54 }
44 55
45 jobject GetApplicationContext() { 56 jobject GetApplicationContext() {
46 DCHECK(g_application_context); 57 DCHECK(g_application_context);
47 return g_application_context; 58 return g_application_context;
48 } 59 }
49 60
50 MethodID::MethodID(JNIEnv* env, const char* class_name, const char* method, 61 jmethodID GetMethodIDFromClassName(JNIEnv* env,
51 const char* jni_signature) { 62 const char* class_name,
63 const char* method,
64 const char* jni_signature) {
65 DCHECK_EQ(std::string::npos, std::string(class_name).find('!'));
66 DCHECK_EQ(std::string::npos, std::string(method).find('!'));
67 DCHECK_EQ(std::string::npos, std::string(jni_signature).find('!'));
68 std::string key(class_name);
69 key += '!';
70 key += method;
71 key += '!';
72 key += jni_signature;
joth 2011/12/02 14:10:13 shame we have to do this everytime we lookup a sym
73
74 MethodIDMap* map = g_method_id_map.Pointer();
75 bool found = false;
76
77 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
78 kUnlocked,
79 kLocked) != kUnlocked) {
80 base::PlatformThread::YieldCurrentThread();
81 }
joth 2011/12/02 14:10:13 looks sufficiently fun to benefit from having some
82 MethodIDMap::const_iterator iter = map->find(key);
83 if (iter != map->end()) {
84 found = true;
85 }
86 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
87
88 // Addition to the map does not invalidate this iterator.
89 if (found) {
90 return iter->second;
91 }
92
52 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name)); 93 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name));
53 id_ = GetMethodID(env, clazz.obj(), method, jni_signature); 94 jmethodID id = GetMethodID(env, clazz.obj(), method, jni_signature);
95
96 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
97 kUnlocked,
98 kLocked) != kUnlocked) {
99 base::PlatformThread::YieldCurrentThread();
100 }
101 // Another thread may have populated the map already.
102 iter = map->find(key);
103 if (iter == map->end()) {
joth 2011/12/02 14:10:13 nit: rather than walk the tree twice here, you can
104 map->insert(std::make_pair(key, id));
105 } else {
106 DCHECK_EQ(id, iter->second);
107 }
108 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
109
110 return id;
54 } 111 }
55 112
56 jmethodID GetMethodID(JNIEnv* env, 113 jmethodID GetMethodID(JNIEnv* env,
57 jclass clazz, 114 jclass clazz,
58 const char* const method, 115 const char* const method,
59 const char* const jni_signature) { 116 const char* const jni_signature) {
60 jmethodID id = env->GetMethodID(clazz, method, jni_signature); 117 jmethodID id = env->GetMethodID(clazz, method, jni_signature);
61 DCHECK(id) << method; 118 DCHECK(id) << method;
62 CheckException(env); 119 CheckException(env);
63 return id; 120 return id;
(...skipping 22 matching lines...) Expand all
86 bool CheckException(JNIEnv* env) { 143 bool CheckException(JNIEnv* env) {
87 if (env->ExceptionCheck() == JNI_FALSE) 144 if (env->ExceptionCheck() == JNI_FALSE)
88 return false; 145 return false;
89 env->ExceptionDescribe(); 146 env->ExceptionDescribe();
90 env->ExceptionClear(); 147 env->ExceptionClear();
91 return true; 148 return true;
92 } 149 }
93 150
94 } // namespace android 151 } // namespace android
95 } // namespace base 152 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698