1 /*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "sdk/android/src/jni/jni_generator_helper.h"
12
13 #include "rtc_base/atomic_ops.h"
14 #include "sdk/android/native_api/jni/class_loader.h"
15
16 namespace webrtc {
17
18 // If |atomic_class_id| set, it'll return immediately. Otherwise, it will look
19 // up the class and store it. If there's a race, we take care to only store one
20 // global reference (and the duplicated effort will happen only once).
LazyGetClass(JNIEnv * env,const char * class_name,std::atomic<jclass> * atomic_class_id)21 jclass LazyGetClass(JNIEnv* env,
22 const char* class_name,
23 std::atomic<jclass>* atomic_class_id) {
24 const jclass value = std::atomic_load(atomic_class_id);
25 if (value)
26 return value;
27 webrtc::ScopedJavaGlobalRef<jclass> clazz(webrtc::GetClass(env, class_name));
28 RTC_CHECK(!clazz.is_null()) << class_name;
29 jclass cas_result = nullptr;
30 if (std::atomic_compare_exchange_strong(atomic_class_id, &cas_result,
31 clazz.obj())) {
32 // We sucessfully stored |clazz| in |atomic_class_id|, so we are
33 // intentionally leaking the global ref since it's now stored there.
34 return clazz.Release();
35 } else {
36 // Some other thread came before us and stored a global pointer in
37 // |atomic_class_id|. Relase our global ref and return the ref from the
38 // other thread.
39 return cas_result;
40 }
41 }
42
43 // If |atomic_method_id| set, it'll return immediately. Otherwise, it will look
44 // up the method id and store it. If there's a race, it's ok since the values
45 // are the same (and the duplicated effort will happen only once).
46 template <MethodID::Type type>
LazyGet(JNIEnv * env,jclass clazz,const char * method_name,const char * jni_signature,std::atomic<jmethodID> * atomic_method_id)47 jmethodID MethodID::LazyGet(JNIEnv* env,
48 jclass clazz,
49 const char* method_name,
50 const char* jni_signature,
51 std::atomic<jmethodID>* atomic_method_id) {
52 const jmethodID value = std::atomic_load(atomic_method_id);
53 if (value)
54 return value;
55 auto get_method_ptr = type == MethodID::TYPE_STATIC
56 ? &JNIEnv::GetStaticMethodID
57 : &JNIEnv::GetMethodID;
58 jmethodID id = (env->*get_method_ptr)(clazz, method_name, jni_signature);
59 CHECK_EXCEPTION(env) << "error during GetMethodID: " << method_name << ", "
60 << jni_signature;
61 RTC_CHECK(id) << method_name << ", " << jni_signature;
62 std::atomic_store(atomic_method_id, id);
63 return id;
64 }
65
66 // Various template instantiations.
67 template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
68 JNIEnv* env,
69 jclass clazz,
70 const char* method_name,
71 const char* jni_signature,
72 std::atomic<jmethodID>* atomic_method_id);
73
74 template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
75 JNIEnv* env,
76 jclass clazz,
77 const char* method_name,
78 const char* jni_signature,
79 std::atomic<jmethodID>* atomic_method_id);
80
81 } // namespace webrtc
82