1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBTEXTCLASSIFIER_UTILS_JAVA_SCOPED_LOCAL_REF_H_ 18 #define LIBTEXTCLASSIFIER_UTILS_JAVA_SCOPED_LOCAL_REF_H_ 19 20 #include <jni.h> 21 #include <memory> 22 #include <type_traits> 23 24 #include "utils/base/logging.h" 25 26 namespace libtextclassifier3 { 27 28 // A deleter to be used with std::unique_ptr to delete JNI local references. 29 class LocalRefDeleter { 30 public: LocalRefDeleter()31 LocalRefDeleter() : env_(nullptr) {} 32 33 // Style guide violating implicit constructor so that the LocalRefDeleter 34 // is implicitly constructed from the second argument to ScopedLocalRef. LocalRefDeleter(JNIEnv * env)35 LocalRefDeleter(JNIEnv* env) : env_(env) {} // NOLINT(runtime/explicit) 36 37 LocalRefDeleter(const LocalRefDeleter& orig) = default; 38 39 // Copy assignment to allow move semantics in ScopedLocalRef. 40 LocalRefDeleter& operator=(const LocalRefDeleter& rhs) { 41 // As the deleter and its state are thread-local, ensure the envs 42 // are consistent but do nothing. 43 TC3_CHECK_EQ(env_, rhs.env_); 44 return *this; 45 } 46 47 // The delete operator. operator()48 void operator()(jobject object) const { 49 if (env_) { 50 env_->DeleteLocalRef(object); 51 } 52 } 53 54 private: 55 // The env_ stashed to use for deletion. Thread-local, don't share! 56 JNIEnv* const env_; 57 }; 58 59 // A smart pointer that deletes a JNI local reference when it goes out 60 // of scope. Usage is: 61 // ScopedLocalRef<jobject> scoped_local(env->JniFunction(), env); 62 // 63 // Note that this class is not thread-safe since it caches JNIEnv in 64 // the deleter. Do not use the same jobject across different threads. 65 template <typename T> 66 using ScopedLocalRef = 67 std::unique_ptr<typename std::remove_pointer<T>::type, LocalRefDeleter>; 68 69 } // namespace libtextclassifier3 70 71 #endif // LIBTEXTCLASSIFIER_UTILS_JAVA_SCOPED_LOCAL_REF_H_ 72