1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/java/jni_helper.h"
9 #include "base/android/jni_android.h"
10 #include "base/lazy_instance.h"
11 #include "base/threading/platform_thread.h"
17 struct MethodIdentifier
{
18 const char* class_name
;
20 const char* jni_signature
;
22 bool operator<(const MethodIdentifier
& other
) const {
23 int r
= strcmp(class_name
, other
.class_name
);
30 r
= strcmp(method
, other
.method
);
37 return strcmp(jni_signature
, other
.jni_signature
) < 0;
41 typedef std::map
<MethodIdentifier
, jmethodID
> MethodIDMap
;
43 const base::subtle::AtomicWord kUnlocked
= 0;
44 const base::subtle::AtomicWord kLocked
= 1;
45 base::subtle::AtomicWord g_method_id_map_lock
= kUnlocked
;
47 base::LazyInstance
<MethodIDMap
> g_method_id_map
= LAZY_INSTANCE_INITIALIZER
;
51 jmethodID
GetMethodIDFromClassName(JNIEnv
* env
,
52 const char* class_name
,
54 const char* jni_signature
) {
56 key
.class_name
= class_name
;
58 key
.jni_signature
= jni_signature
;
60 MethodIDMap
* map
= g_method_id_map
.Pointer();
63 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock
,
65 kLocked
) != kUnlocked
) {
66 base::PlatformThread::YieldCurrentThread();
68 MethodIDMap::const_iterator iter
= map
->find(key
);
69 if (iter
!= map
->end()) {
72 base::subtle::Release_Store(&g_method_id_map_lock
, kUnlocked
);
74 // Addition to the map does not invalidate this iterator.
79 base::android::ScopedJavaLocalRef
<jclass
> clazz(
80 env
, env
->FindClass(class_name
));
81 jmethodID id
= base::android::MethodID::Get
<
82 base::android::MethodID::TYPE_INSTANCE
>(
83 env
, clazz
.obj(), method
, jni_signature
);
85 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock
,
87 kLocked
) != kUnlocked
) {
88 base::PlatformThread::YieldCurrentThread();
90 // Another thread may have populated the map already.
91 std::pair
<MethodIDMap::const_iterator
, bool> result
=
92 map
->insert(std::make_pair(key
, id
));
93 DCHECK_EQ(id
, result
.first
->second
);
94 base::subtle::Release_Store(&g_method_id_map_lock
, kUnlocked
);
99 } // namespace content