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 "sdk/android/native_api/jni/class_loader.h"
14
15 namespace webrtc {
16
17 // If `atomic_class_id` set, it'll return immediately. Otherwise, it will look
18 // up the class and store it. If there's a race, we take care to only store one
19 // global reference (and the duplicated effort will happen only once).
LazyGetClass(JNIEnv * env,const char * class_name,std::atomic<jclass> * atomic_class_id)20 jclass LazyGetClass(JNIEnv* env,
21 const char* class_name,
22 std::atomic<jclass>* atomic_class_id) {
23 const jclass value = std::atomic_load(atomic_class_id);
24 if (value)
25 return value;
26 webrtc::ScopedJavaGlobalRef<jclass> clazz(webrtc::GetClass(env, class_name));
27 RTC_CHECK(!clazz.is_null()) << class_name;
28 jclass cas_result = nullptr;
29 if (std::atomic_compare_exchange_strong(atomic_class_id, &cas_result,
30 clazz.obj())) {
31 // We sucessfully stored `clazz` in `atomic_class_id`, so we are
32 // intentionally leaking the global ref since it's now stored there.
33 return clazz.Release();
34 } else {
35 // Some other thread came before us and stored a global pointer in
36 // `atomic_class_id`. Relase our global ref and return the ref from the
37 // other thread.
38 return cas_result;
39 }
40 }
41
42 // If `atomic_method_id` set, it'll return immediately. Otherwise, it will look
43 // up the method id and store it. If there's a race, it's ok since the values
44 // are the same (and the duplicated effort will happen only once).
45 template <MethodID::Type type>
LazyGet(JNIEnv * env,jclass clazz,const char * method_name,const char * jni_signature,std::atomic<jmethodID> * atomic_method_id)46 jmethodID MethodID::LazyGet(JNIEnv* env,
47 jclass clazz,
48 const char* method_name,
49 const char* jni_signature,
50 std::atomic<jmethodID>* atomic_method_id) {
51 const jmethodID value = std::atomic_load(atomic_method_id);
52 if (value)
53 return value;
54 auto get_method_ptr = type == MethodID::TYPE_STATIC
55 ? &JNIEnv::GetStaticMethodID
56 : &JNIEnv::GetMethodID;
57 jmethodID id = (env->*get_method_ptr)(clazz, method_name, jni_signature);
58 CHECK_EXCEPTION(env) << "error during GetMethodID: " << method_name << ", "
59 << jni_signature;
60 RTC_CHECK(id) << method_name << ", " << jni_signature;
61 std::atomic_store(atomic_method_id, id);
62 return id;
63 }
64
65 // Various template instantiations.
66 template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
67 JNIEnv* env,
68 jclass clazz,
69 const char* method_name,
70 const char* jni_signature,
71 std::atomic<jmethodID>* atomic_method_id);
72
73 template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
74 JNIEnv* env,
75 jclass clazz,
76 const char* method_name,
77 const char* jni_signature,
78 std::atomic<jmethodID>* atomic_method_id);
79
80 } // namespace webrtc
81