Skip to content

Commit

Permalink
feat(java): SCAPIX_JAVA_AUTO_ATTACH_THREAD option
Browse files Browse the repository at this point in the history
With SCAPIX_JAVA_AUTO_ATTACH_THREAD option,
Scapix automatically calls AttachCurrentThread()
if current thread is not attached to JNI Env.
  • Loading branch information
Boris-Rasin committed May 15, 2022
1 parent 0120e5a commit 0256e3f
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 170 deletions.
2 changes: 1 addition & 1 deletion source/scapix/link/java/detail/api/ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#ifndef SCAPIX_LINK_JAVA_DETAIL_API_REF_H
#define SCAPIX_LINK_JAVA_DETAIL_API_REF_H

#include <scapix/link/java/detail/config.h>
#include <scapix/link/java/env.h>

namespace scapix::link::java::detail::api {

Expand Down
64 changes: 0 additions & 64 deletions source/scapix/link/java/detail/config.h

This file was deleted.

81 changes: 79 additions & 2 deletions source/scapix/link/java/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,92 @@
#ifndef SCAPIX_LINK_JAVA_ENV_H
#define SCAPIX_LINK_JAVA_ENV_H

#include <scapix/link/java/detail/config.h>
#include <jni.h>
#include <boost/config.hpp>
#include <scapix/core/function_traits.h>

namespace scapix::link::java {
namespace detail {

/*
jni.h (JDK) uses void** type:
jint JNI_CreateJavaVM(JavaVM**, void**, void*);
jint AttachCurrentThread(JavaVM*, void**, void*);
jint AttachCurrentThreadAsDaemon(JavaVM*, void**, void*);
jni.h (Android NDK) uses JNIEnv** type:
jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
jint AttachCurrentThread(JavaVM*, JNIEnv**, void*);
jint AttachCurrentThreadAsDaemon(JavaVM*, JNIEnv**, void*);
*/

using jnienv_type = function_traits<std::remove_pointer_t<decltype(&JNI_CreateJavaVM)>>::argument_type<1>;

inline JavaVM* jvm_ptr;

inline JavaVM* jvm() noexcept
{
return jvm_ptr;
}

struct thread_env
{
~thread_env()
{
if (ptr)
jvm()->DetachCurrentThread();
}

jnienv_type addr() { return reinterpret_cast<jnienv_type>(&ptr); }
void** addr_void() { return reinterpret_cast<void**>(&ptr); }

JNIEnv* ptr = nullptr;
};

inline thread_local thread_env env_;

} // namespace detail

inline jint get_env(jint version = JNI_VERSION_1_6) noexcept
{
return detail::jvm()->GetEnv((void**)&detail::env(), version);
return detail::jvm()->GetEnv(detail::env_.addr_void(), version);
}

inline jint attach_current_thread(void *args = nullptr) noexcept
{
return detail::jvm()->AttachCurrentThread(detail::env_.addr(), args);
}

inline jint attach_current_thread_as_daemon(void *args = nullptr) noexcept
{
return detail::jvm()->AttachCurrentThreadAsDaemon(detail::env_.addr(), args);
}

inline jint detach_current_thread() noexcept
{
detail::env_.ptr = nullptr;
return detail::jvm()->DetachCurrentThread();
}

namespace detail {

inline JNIEnv* env() noexcept
{
#ifdef SCAPIX_JAVA_AUTO_ATTACH_THREAD

if (BOOST_UNLIKELY(!env_.ptr))
attach_current_thread();

#endif

return env_.ptr;
}

} // namespace detail
} // namespace scapix::link::java

#endif // SCAPIX_LINK_JAVA_ENV_H
4 changes: 2 additions & 2 deletions source/scapix/link/java/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class class_loader

inline jint on_load(JavaVM *vm, void *reserved) noexcept
{
detail::jvm() = vm;
detail::jvm_ptr = vm;
get_env();

#ifdef SCAPIX_CACHE_CLASS_LOADER
Expand All @@ -61,7 +61,7 @@ inline jint on_load(JavaVM *vm, void *reserved) noexcept

inline void on_unload(JavaVM *vm, void *reserved) noexcept
{
detail::jvm() = nullptr;
detail::jvm_ptr = nullptr;
}

} // namespace scapix::link::java
Expand Down
4 changes: 2 additions & 2 deletions source/scapix/link/java/native_method.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class native_method
{
static param_type<JniR> func(JNIEnv* env, jobject thiz, param_type<JniArgs>... args)
{
detail::env() = env;
detail::env_.ptr = env;

try
{
Expand Down Expand Up @@ -156,7 +156,7 @@ class native_method
{
static param_type<JniR> func(JNIEnv* env, jclass clazz, param_type<JniArgs>... args)
{
detail::env() = env;
detail::env_.ptr = env;

try
{
Expand Down
93 changes: 0 additions & 93 deletions source/scapix/link/java/thread.h

This file was deleted.

2 changes: 1 addition & 1 deletion source/scapix/link/java/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <type_traits>
#include <scapix/meta/string.h>
#include <scapix/link/java/detail/config.h>
#include <scapix/link/java/env.h>

namespace scapix::link::java {

Expand Down
10 changes: 5 additions & 5 deletions source/scapix/link/java/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,32 @@
#ifndef SCAPIX_LINK_JAVA_VM_H
#define SCAPIX_LINK_JAVA_VM_H

#include <scapix/link/java/detail/config.h>
#include <scapix/link/java/env.h>

namespace scapix::link::java {

inline bool init_created_vm() noexcept
{
jint count;
JNI_GetCreatedJavaVMs(&detail::jvm(), 1, &count);
JNI_GetCreatedJavaVMs(&detail::jvm_ptr, 1, &count);
return count != 0;
}

inline void deinit_created_vm() noexcept
{
detail::jvm() = nullptr;
detail::jvm_ptr = nullptr;
}

inline jint create_vm(void* args) noexcept
{
return JNI_CreateJavaVM(&detail::jvm(), reinterpret_cast<detail::jnienv_type>(&detail::env()), args);
return JNI_CreateJavaVM(&detail::jvm_ptr, detail::env_.addr(), args);
}

inline jint destroy_vm() noexcept
{
auto r = detail::jvm()->DestroyJavaVM();
if (r == JNI_OK)
detail::jvm() = nullptr;
detail::jvm_ptr = nullptr;
return r;
}

Expand Down

0 comments on commit 0256e3f

Please sign in to comment.