Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move implementation of CppProxyBase to cpp #1579

Merged
merged 1 commit into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ namespace {{.}}
namespace jni
{

class {{resolveName "mangled"}}_CppProxy : public CppProxyBase{{!!
class {{resolveName "mangled"}}_CppProxy final : public CppProxyBase{{!!
}}{{#instanceOf this "LimeInterface"}}, public {{resolveName "C++ FQN"}}{{/instanceOf}} {
public:
{{resolveName "mangled"}}_CppProxy( JNIEnv* _jenv, JniReference<jobject> globalRef, jint _jHashCode );
{{resolveName "mangled"}}_CppProxy( JniReference<jobject> globalRef, jint _jHashCode ) noexcept;
{{resolveName "mangled"}}_CppProxy( const {{resolveName "mangled"}}_CppProxy& ) = delete;
{{resolveName "mangled"}}_CppProxy& operator=( const {{resolveName "mangled"}}_CppProxy& ) = delete;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ namespace jni
{

{{#container}}
{{resolveName "mangled"}}_CppProxy::{{resolveName "mangled"}}_CppProxy( JNIEnv* _jenv, JniReference<jobject> globalRef, jint _jHashCode )
: CppProxyBase( _jenv, std::move( globalRef ), _jHashCode, "{{resolveName "mangled"}}" ) {
{{resolveName "mangled"}}_CppProxy::{{resolveName "mangled"}}_CppProxy(JniReference<jobject> globalRef, jint _jHashCode) noexcept
: CppProxyBase(std::move(globalRef), _jHashCode, "{{resolveName "mangled"}}") {
}
{{#inheritedFunctions}}{{#unless isStatic}}
{{>proxyMethodImpl}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@
#include "JniCallbackErrorChecking.h"

#include <memory>
#include <mutex>
#include <new>
#include <string>
#include <unordered_map>

{{#internalNamespace}}
namespace {{.}}
Expand All @@ -45,6 +43,28 @@ namespace jni
class JNIEXPORT CppProxyBase
{
private:
using ReverseCacheKey = const void*;
using ProxyFactoryResult = std::pair<std::shared_ptr<CppProxyBase>, ReverseCacheKey>;
using ProxyFactoryFun = ProxyFactoryResult(*)(JniReference<jobject>, jint);

template<typename ResultType, typename ImplType>
struct ProxyFactory {
static ProxyFactoryResult
create(JniReference<jobject> globalRef, jint jHashCode)
{
ImplType* const newProxyInstance = new (::std::nothrow ) ImplType{std::move(globalRef), jHashCode};
const ResultType* const castedToResult = newProxyInstance;
return std::make_pair(std::shared_ptr<ImplType>{newProxyInstance}, castedToResult);
}
};

static std::shared_ptr<CppProxyBase>
createProxyImpl( JNIEnv* jenv,
const JniReference<jobject>& jobj,
const ::std::string& type_key,
bool do_cache,
ProxyFactoryFun factory);

template < typename ResultType, typename ImplType >
static void
createProxy( JNIEnv* jenv,
Expand All @@ -53,38 +73,9 @@ private:
bool do_cache,
::std::shared_ptr< ResultType >& result )
{
JniReference<jobject> globalRef = new_global_ref( jenv, jobj.get() );
jint jHashCode = getHashCode( jenv, jobj.get() );
ProxyCacheKey key{globalRef.get(), jHashCode, type_key};

::std::lock_guard< GlobalJniLock > lock( sGlobalJniLock );
sGlobalJniLock.setJniEnvForCurrentThread( jenv );

if (do_cache) {
auto iterator = sProxyCache.find( key );
if ( iterator != sProxyCache.end( ) )
{
auto cachedProxy = iterator->second.lock( );
if ( cachedProxy )
{
result = ::std::static_pointer_cast< ImplType >( cachedProxy );
return;
}
}
}

auto newProxyInstance = new (::std::nothrow ) ImplType( jenv, std::move(globalRef), jHashCode );
if ( newProxyInstance == nullptr )
if (auto proxy = createProxyImpl( jenv, jobj, type_key, do_cache, &ProxyFactory<ResultType, ImplType>::create ))
{
throw_runtime_exception( jenv, "Cannot allocate native memory." );
return;
}
auto newProxy = ::std::shared_ptr< ImplType >( newProxyInstance );
result = newProxy;

if (do_cache) {
sProxyCache[ key ] = ::std::weak_ptr< ImplType >( newProxy );
registerInReverseCache(newProxyInstance, result.get(), key.jObject);
result = ::std::static_pointer_cast< ImplType >( proxy );;
}
}

Expand Down Expand Up @@ -115,7 +106,7 @@ public:
}

protected:
CppProxyBase( JNIEnv* jenv, JniReference<jobject> globalRef, jint jHashCode, ::std::string type_key );
CppProxyBase(JniReference<jobject> globalRef, jint jHashCode, ::std::string type_key) noexcept;

virtual ~CppProxyBase( );

Expand All @@ -129,69 +120,22 @@ protected:
return call_java_method<ResultType>(jniEnv, mGlobalRef, methodName, jniSignature, args...);
}

static JNIEnv* getJniEnvironment( );

private:

struct ProxyCacheKey
{
jobject jObject;
jint jHashCode;
::std::string type_key;

bool operator==( const ProxyCacheKey& other ) const;
};

struct ProxyCacheKeyHash
{
inline size_t
operator( )( const ProxyCacheKey& key ) const
{
size_t result = 7;
result = 31 * result + key.jHashCode;
result = 31 * result + ::std::hash<::std::string>{}(key.type_key);
return result;
}
};

using ReverseCacheKey = const void*;

class GlobalJniLock {
public:
void lock( );
void unlock( );

void setJniEnvForCurrentThread( JNIEnv* env );
JNIEnv* getJniEnvForCurrentThread( );

private:
::std::mutex cacheMutex;
JNIEnv* jniEnvForCurrentThread = nullptr;
};

using ProxyCache
= ::std::unordered_map< ProxyCacheKey, ::std::weak_ptr< CppProxyBase >, ProxyCacheKeyHash >;
using ReverseProxyCache = ::std::unordered_map<ReverseCacheKey, jobject>;
static JNIEnv* getJniEnvironment( ) noexcept;

private:
static jint getHashCode( JNIEnv* jniEnv, jobject jObj );

static void registerInReverseCache( CppProxyBase* proxyBase,
ReverseCacheKey reverseCacheKey,
const jobject& jObj );
jobject jObj );
void removeSelfFromReverseCache( );
static JniReference<jobject> getJavaObjectFromReverseCache(JNIEnv* jniEnv, ReverseCacheKey reverseCacheKey);

private:
JniReference<jobject> mGlobalRef;
jint jHashCode;
const JniReference<jobject> mGlobalRef;
const jint jHashCode;
ReverseCacheKey mReverseCacheKey = nullptr;
const ::std::string type_key;

protected:
static ProxyCache sProxyCache;
static ReverseProxyCache sReverseProxyCache;
static GlobalJniLock sGlobalJniLock;
};

}
Expand Down
Loading
Loading