Skip to content

Commit

Permalink
Move implementation of CppProxyBase to cpp (#1579)
Browse files Browse the repository at this point in the history
Signed-off-by: Yauheni Khnykin <[email protected]>
  • Loading branch information
Hsilgos authored Apr 22, 2024
1 parent d583fe6 commit 45b2bb6
Show file tree
Hide file tree
Showing 33 changed files with 1,086 additions and 274 deletions.
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

0 comments on commit 45b2bb6

Please sign in to comment.