• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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