Loading...
Searching...
No Matches
unique.hpp
Go to the documentation of this file.
#pragma once
namespace jni
{
/*
Ownership type and main interface for high-level references. Client code using the high-level
API will most often work with values of this class template, using the following aliases:
* Global<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteGlobalRef>>,
* Weak<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteWeakGlobalRef>>,
* Local<P>, a.k.a. Unique<T, LocalRefDeleter>,
where P is Object<>, Class<>, or Array<>.
`Unique` is an ownership class with a deletion policy that's parameterized both
by the appropriate method to delete the reference (global, weak, or local) and
(for global and weak references), a choice about how to obtain the JNIEnv that's
necessary to call the deletion method. The default policy is to delete the reference
using the same JNIEnv as was passed to the constructor, but in cases where the
object may be deleted on a different thread (commonly, the Java finalizer thread),
EnvGettingDeleter or EnvAttachingDeleter may be needed.
Object<>, Class<>, or Array<> -- the underlying and inherited types used for
the template parameter T -- are not publicly constructible or destructible. This
is to ensure that code works only with ownership types which release the reference
at an appropriate time. Our experience has shown that this is important even for
local references; the default JVM cleanup behaviors for local references are not
enough to ensure that the local reference table never overflows.
You may also pass or receive C++ references when you wish to borrow rather than take
ownership. For example, receiving parameters for a native method implementation should be
C++ references, reflecting the fact that JVM implementations prohibit explicitly releasing
this form of local reference. However, if you need to store or copy the reference, you
will need to use a method such as `NewGlobalRef` that copies at the reference level.
`Unique`, `Object<>`, etc., are not themselves copyable.
*/
template < class T, class D >
class Unique : public T
{
private:
D deleter;
Unique(const Unique&) = delete;
Unique& operator=(const Unique&) = delete;
public:
using Base = T;
using UntaggedType = typename T::UntaggedType;
explicit Unique(std::nullptr_t ptr = nullptr)
: T(ptr),
deleter() {}
explicit Unique(JNIEnv& env, UntaggedType* ptr)
: T(ptr),
deleter(env) {}
Unique(Unique&& other)
: T(other.release()),
deleter(std::move(other.get_deleter())) {}
template < class U >
Unique(Unique<U, D>&& other, std::enable_if_t<std::is_convertible<const U&, const T&>::value>* = nullptr)
: T(other.release()),
deleter(std::move(other.get_deleter())) {}
~Unique()
{
reset();
}
Unique& operator=(Unique&& other)
{
reset(other.release());
deleter = std::move(other.deleter);
return *this;
}
void reset(UntaggedType* ptr = nullptr)
{
UntaggedType* current = this->get();
T::reset(ptr);
if (current)
{
get_deleter()(current);
}
}
UntaggedType* release()
{
UntaggedType* current = this->get();
T::reset(nullptr);
return current;
}
D& get_deleter() { return deleter; }
const D& get_deleter() const { return deleter; }
};
template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
using Global = Unique< T, Deleter<&JNIEnv::DeleteGlobalRef> >;
template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
using Weak = Unique< T, Deleter<&JNIEnv::DeleteWeakGlobalRef> >;
// Not parameterized by Deleter because local references should be short-lived enough
// that DefaultRefDeleter suffices in all cases.
template < class T >
using Local = Unique< T, DefaultRefDeleter<&JNIEnv::DeleteLocalRef> >;
// Special case for JNI-provided input parameters to native methods, which apparently
// should not be explicitly deleted (https://bugs.chromium.org/p/chromium/issues/detail?id=506850).
struct NullDeleter
{
NullDeleter() = default;
NullDeleter(JNIEnv&) {}
void operator()(jobject*) const {}
};
template < class T >
using Input = Unique< T, NullDeleter >;
template < class T >
struct RemoveUnique
{
using Type = T;
};
template < class T, class D >
struct RemoveUnique< Unique<T, D> >
{
using Type = T;
};
template < class T >
using RemoveUniqueType = typename RemoveUnique<T>::Type;
template < class T >
auto ReleaseUnique(T primitive)
{
return primitive;
}
template < class T, class D >
auto ReleaseUnique(Unique<T, D>&& t)
{
return t.release();
}
template < template < RefDeletionMethod > class Deleter, class T >
auto NewGlobal(JNIEnv& env, const T& t)
{
return Global<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewGlobalRef(env, t.get()).release()));
}
template < class T >
auto NewGlobal(JNIEnv& env, const T& t)
{
return NewGlobal<DefaultRefDeleter>(env, t);
}
// Attempt to promote a weak reference to a strong one. Returns an empty result
// if the weak reference has expired.
//
// Beware that the semantics of JNI weak references are weaker than is typically
// desired: a JNI weak reference may still be promoted to a non-null strong reference
// even during finalization. Consider using jni::WeakReference<T> instead.
template < template < RefDeletionMethod > class Deleter, class T, template < RefDeletionMethod > class WeakDeleter >
Global<T, Deleter> NewGlobal(JNIEnv& env, const Weak<T, WeakDeleter>& t)
{
jobject* obj = Wrap<jobject*>(env.NewGlobalRef(Unwrap(t->get())));
CheckJavaException(env);
return Global<T, Deleter>(env, obj);
}
template < class T >
Global<T> NewGlobal(JNIEnv& env, const Weak<T>& t)
{
return NewGlobal<DefaultRefDeleter>(env, t);
}
template < template < RefDeletionMethod > class Deleter, class T >
auto NewWeak(JNIEnv& env, const T& t)
{
return Weak<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewWeakGlobalRef(env, t.get()).release()));
}
template < class T >
auto NewWeak(JNIEnv& env, const T& t)
{
return NewWeak<DefaultRefDeleter>(env, t);
}
template < class T >
auto NewLocal(JNIEnv& env, const T& t)
{
return Local<RemoveUniqueType<T>>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewLocalRef(env, t.get()).release()));
}
// Attempt to promote a weak reference to a strong one. Returns an empty result
// if the weak reference has expired.
//
// Beware that the semantics of JNI weak references are weaker than is typically
// desired: a JNI weak reference may still be promoted to a non-null strong reference
// even during finalization. Consider using jni::WeakReference<T> instead.
template < class T, template < RefDeletionMethod > class WeakDeleter >
Local<T> NewLocal(JNIEnv& env, const Weak<T, WeakDeleter>& t)
{
jobject* obj = Wrap<jobject*>(env.NewLocalRef(Unwrap(t->get())));
CheckJavaException(env);
return Local<T>(env, obj);
}
}
jni::DefaultRefDeleter
Definition ownership.hpp:27
jni::Unique
Definition unique.hpp:39
jni::Unique::UntaggedType
typename T::UntaggedType UntaggedType
Definition unique.hpp:48
jni::Unique::Unique
Unique(JNIEnv &env, UntaggedType *ptr)
Definition unique.hpp:54
jni::Unique::Unique
Unique(std::nullptr_t ptr=nullptr)
Definition unique.hpp:50
jni::Unique::Base
T Base
Definition unique.hpp:47
jni::Unique::Unique
Unique(Unique< U, D > &&other, std::enable_if_t< std::is_convertible< const U &, const T & >::value > *=nullptr)
Definition unique.hpp:63
jni::Unique::Unique
Unique(Unique &&other)
Definition unique.hpp:58
jni::Unique::operator=
Unique & operator=(Unique &&other)
Definition unique.hpp:72
jni::Unique::get_deleter
const D & get_deleter() const
Definition unique.hpp:97
jni::Unique< T, Deleter<&JNIEnv::DeleteGlobalRef > >::release
UntaggedType * release()
Definition unique.hpp:89
jni::Unique::~Unique
~Unique()
Definition unique.hpp:67
jni::Unique< T, Deleter<&JNIEnv::DeleteGlobalRef > >::get_deleter
Deleter<&JNIEnv::DeleteGlobalRef > & get_deleter()
Definition unique.hpp:96
jni::Unique::reset
void reset(UntaggedType *ptr=nullptr)
Definition unique.hpp:79
jni
Definition advanced_ownership.hpp:6
jni::NewGlobalRef
UniqueGlobalRef< T, Deleter > NewGlobalRef(JNIEnv &env, T *t)
Definition functions.hpp:132
jni::NewWeakGlobalRef
UniqueWeakGlobalRef< T, Deleter > NewWeakGlobalRef(JNIEnv &env, T *t)
Definition functions.hpp:205
jni::CheckJavaException
R CheckJavaException(JNIEnv &env, R &&r)
Definition errors.hpp:61
jni::Global
Unique< T, Deleter<&JNIEnv::DeleteGlobalRef > > Global
Definition unique.hpp:102
jni::NewLocal
auto NewLocal(JNIEnv &env, const T &t)
Definition unique.hpp:202
jni::ReleaseUnique
auto ReleaseUnique(T primitive)
Definition unique.hpp:143
jni::NewWeak
auto NewWeak(JNIEnv &env, const T &t)
Definition unique.hpp:189
jni::Input
Unique< T, NullDeleter > Input
Definition unique.hpp:123
jni::Wrap
auto Wrap(U &&u)
Definition wrapping.hpp:16
jni::Weak
Unique< T, Deleter<&JNIEnv::DeleteWeakGlobalRef > > Weak
Definition unique.hpp:105
jni::Unwrap
auto Unwrap(W &&w)
Definition wrapping.hpp:22
jni::NewLocalRef
UniqueLocalRef< T > NewLocalRef(JNIEnv &env, T *t)
Definition functions.hpp:172
jni::RemoveUniqueType
typename RemoveUnique< T >::Type RemoveUniqueType
Definition unique.hpp:139
jni::NewGlobal
auto NewGlobal(JNIEnv &env, const T &t)
Definition unique.hpp:156
jni::Local
Unique< T, DefaultRefDeleter<&JNIEnv::DeleteLocalRef > > Local
Definition unique.hpp:110
std
Definition errors.hpp:10
jni::NullDeleter::NullDeleter
NullDeleter(JNIEnv &)
Definition unique.hpp:118
jni::NullDeleter::operator()
void operator()(jobject *) const
Definition unique.hpp:119
jni::NullDeleter::NullDeleter
NullDeleter()=default
jni::RemoveUnique< Unique< T, D > >::Type
T Type
Definition unique.hpp:135
jni::RemoveUnique
Definition unique.hpp:128
jni::RemoveUnique::Type
T Type
Definition unique.hpp:129
jni::jobject
Definition types.hpp:31