diff options
Diffstat (limited to 'libs/samba/src/main/cpp/jni.hpp')
| -rw-r--r-- | libs/samba/src/main/cpp/jni.hpp | 85 |
1 files changed, 63 insertions, 22 deletions
diff --git a/libs/samba/src/main/cpp/jni.hpp b/libs/samba/src/main/cpp/jni.hpp index 450fa71..3b5078a 100644 --- a/libs/samba/src/main/cpp/jni.hpp +++ b/libs/samba/src/main/cpp/jni.hpp @@ -15,28 +15,30 @@ namespace internal { void _abort_if_not_ok(const char *file, int line, jint ret); void _abort_with_exception(const char* file, int line, JNIEnv* env); +JNIEnv* NonFatalAttachCurrentThread(); + } // namespace internal template<class T> class Ref { public: - constexpr Ref() : env_(nullptr), ptr_(0) {} + constexpr Ref() : ptr_(nullptr) {} + constexpr Ref(std::nullptr_t) : ptr_(nullptr) {} Ref(const Ref<T>&) = delete; - [[nodiscard]] JNIEnv* env() const { return env_; } [[nodiscard]] T get() const { return ptr_; } [[nodiscard]] T release() { auto ret = release_to_local(); - ptr_ = 0; + ptr_ = nullptr; return ret; } void reset() { del(); - ptr_ = 0; + ptr_ = nullptr; } - explicit operator bool() const { return ptr_ != 0; } + explicit operator bool() const { return ptr_ != nullptr; } protected: Ref(JNIEnv* env, T ptr): env_(env), ptr_(ptr) {} @@ -49,9 +51,17 @@ class Ref { T ptr_; }; +constexpr jint JNI_VERSION = JNI_VERSION_1_2; + +JNIEnv* AttachCurrentThread(); + +JNIEnv* OnLoad(JavaVM* vm); + template<class T> class LocalRef : public Ref<T> { public: + constexpr LocalRef(): Ref<T>() {} + constexpr LocalRef(std::nullptr_t): Ref<T>() {} LocalRef(JNIEnv* env, T ptr): Ref<T>(env, ptr) {} ~LocalRef() override { free(); } @@ -59,6 +69,13 @@ class LocalRef : public Ref<T> { LocalRef& operator=(const Ref<T>& other) = delete; + LocalRef& operator=(LocalRef<T> &&ref) noexcept { + free(); + this->env_ = ref.env_; + this->ptr_ = ref.release(); + return *this; + } + protected: T release_to_local() override { return this->ptr_; } void del() override { free(); } @@ -82,7 +99,7 @@ class ParamRef : public Ref<T> { T release_to_local() override { if (this->ptr_) return static_cast<T>(this->env_->NewLocalRef(static_cast<jobject>(this->ptr_))); - return 0; + return nullptr; } void del() override {} }; @@ -90,43 +107,67 @@ class ParamRef : public Ref<T> { template<class T> class GlobalRef : public Ref<T> { public: - GlobalRef(JNIEnv* env, T ptr) : Ref<T>(env, ptr ? static_cast<T>(env->NewGlobalRef(static_cast<jobject>(ptr))) : 0) {} - explicit GlobalRef(const Ref<T>& other) : Ref<T>(other.env(), other ? static_cast<T>(other.env()->NewGlobalRef(static_cast<jobject>(other.get()))) : 0) {} + constexpr GlobalRef() : Ref<T>() {} + constexpr GlobalRef(std::nullptr_t) : Ref<T>() {} + GlobalRef(JNIEnv* env, T ptr) : Ref<T>() { + if (ptr) { + if (!env) + env = AttachCurrentThread(); + this->ptr_ = static_cast<T>(env->NewGlobalRef(static_cast<jobject>(ptr))); + } + } + GlobalRef(const Ref<T>& other) : Ref<T>() { + if (other) { + auto* env = AttachCurrentThread(); + this->ptr_ = static_cast<T>(env->NewGlobalRef(static_cast<jobject>(other.get()))); + } + } + GlobalRef(GlobalRef<T>&& other) noexcept : Ref<T>(nullptr, other.ptr_) { + other.ptr_ = nullptr; + return *this; + } ~GlobalRef() override { free(); } GlobalRef& operator=(const Ref<T>& other) { free(); - this->env_ = other.env(); - this->ptr_ = other ? static_cast<T>(this->env_->NewGlobalRef(static_cast<jobject>(other.get()))) : 0; + if (other) { + auto* env = AttachCurrentThread(); + this->ptr_ = other ? static_cast<T>(env->NewGlobalRef(static_cast<jobject>(other.get()))) : nullptr; + } else { + this->ptr_ = nullptr; + } return *this; } + GlobalRef& operator=(GlobalRef<T>&& other) { + free(); + this->ptr_ = other.ptr_; + other.ptr_ = nullptr; + } + protected: T release_to_local() override { if (this->ptr_) { - auto ret = static_cast<T>(this->env_->NewLocalRef( - static_cast<jobject>(this->ptr_))); - free(); + auto* env = AttachCurrentThread(); + auto ret = static_cast<T>(env->NewLocalRef(static_cast<jobject>(this->ptr_))); + env->DeleteGlobalRef(static_cast<jobject>(this->ptr_)); return ret; } - return 0; + return nullptr; } void del() override { free(); } private: void free() { - if (this->ptr_) - this->env_->DeleteGlobalRef(this->ptr_); + if (this->ptr_) { + auto* env = internal::NonFatalAttachCurrentThread(); + if (env) + env->DeleteGlobalRef(static_cast<jobject>(this->ptr_)); + } } }; -constexpr jint JNI_VERSION = JNI_VERSION_1_2; - -JNIEnv* AttachCurrentThread(); - -JNIEnv* OnLoad(JavaVM* vm); - LocalRef<jclass> FindClass(JNIEnv *env, const char *name); LocalRef<jthrowable> ExceptionOccurred(JNIEnv* env); |
