Home | History | Annotate | Download | only in java
      1 /*
      2  * Copyright (C) 2017 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_UTIL_JAVA_SCOPED_LOCAL_REF_H_
     18 #define LIBTEXTCLASSIFIER_UTIL_JAVA_SCOPED_LOCAL_REF_H_
     19 
     20 #include <jni.h>
     21 #include <memory>
     22 #include <type_traits>
     23 
     24 #include "util/base/logging.h"
     25 
     26 namespace libtextclassifier2 {
     27 
     28 // A deleter to be used with std::unique_ptr to delete JNI local references.
     29 class LocalRefDeleter {
     30  public:
     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.
     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     TC_CHECK_EQ(env_, rhs.env_);
     44     return *this;
     45   }
     46 
     47   // The delete 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 libtextclassifier2
     70 
     71 #endif  // LIBTEXTCLASSIFIER_UTIL_JAVA_SCOPED_LOCAL_REF_H_
     72