lime
Lime is a C++ library implementing Open Whisper System Signal protocol
unique.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 namespace jni
4  {
5  /*
6  Ownership type and main interface for high-level references. Client code using the high-level
7  API will most often work with values of this class template, using the following aliases:
8 
9  * Global<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteGlobalRef>>,
10  * Weak<P>, a.k.a. Unique<T, DefaultRefDeleter<&JNIEnv::DeleteWeakGlobalRef>>,
11  * Local<P>, a.k.a. Unique<T, LocalRefDeleter>,
12 
13  where P is Object<>, Class<>, or Array<>.
14 
15  `Unique` is an ownership class with a deletion policy that's parameterized both
16  by the appropriate method to delete the reference (global, weak, or local) and
17  (for global and weak references), a choice about how to obtain the JNIEnv that's
18  necessary to call the deletion method. The default policy is to delete the reference
19  using the same JNIEnv as was passed to the constructor, but in cases where the
20  object may be deleted on a different thread (commonly, the Java finalizer thread),
21  EnvGettingDeleter or EnvAttachingDeleter may be needed.
22 
23  Object<>, Class<>, or Array<> -- the underlying and inherited types used for
24  the template parameter T -- are not publicly constructible or destructible. This
25  is to ensure that code works only with ownership types which release the reference
26  at an appropriate time. Our experience has shown that this is important even for
27  local references; the default JVM cleanup behaviors for local references are not
28  enough to ensure that the local reference table never overflows.
29 
30  You may also pass or receive C++ references when you wish to borrow rather than take
31  ownership. For example, receiving parameters for a native method implementation should be
32  C++ references, reflecting the fact that JVM implementations prohibit explicitly releasing
33  this form of local reference. However, if you need to store or copy the reference, you
34  will need to use a method such as `NewGlobalRef` that copies at the reference level.
35  `Unique`, `Object<>`, etc., are not themselves copyable.
36  */
37  template < class T, class D >
38  class Unique : public T
39  {
40  private:
41  D deleter;
42 
43  Unique(const Unique&) = delete;
44  Unique& operator=(const Unique&) = delete;
45 
46  public:
47  using Base = T;
48  using UntaggedType = typename T::UntaggedType;
49 
50  explicit Unique(std::nullptr_t ptr = nullptr)
51  : T(ptr),
52  deleter() {}
53 
54  explicit Unique(JNIEnv& env, UntaggedType* ptr)
55  : T(ptr),
56  deleter(env) {}
57 
58  Unique(Unique&& other)
59  : T(other.release()),
60  deleter(std::move(other.get_deleter())) {}
61 
62  template < class U >
63  Unique(Unique<U, D>&& other, std::enable_if_t<std::is_convertible<const U&, const T&>::value>* = nullptr)
64  : T(other.release()),
65  deleter(std::move(other.get_deleter())) {}
66 
68  {
69  reset();
70  }
71 
73  {
74  reset(other.release());
75  deleter = std::move(other.deleter);
76  return *this;
77  }
78 
79  void reset(UntaggedType* ptr = nullptr)
80  {
81  UntaggedType* current = this->get();
82  T::reset(ptr);
83  if (current)
84  {
85  get_deleter()(current);
86  }
87  }
88 
90  {
91  UntaggedType* current = this->get();
92  T::reset(nullptr);
93  return current;
94  }
95 
96  D& get_deleter() { return deleter; }
97  const D& get_deleter() const { return deleter; }
98  };
99 
100 
101  template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
103 
104  template < class T, template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
106 
107  // Not parameterized by Deleter because local references should be short-lived enough
108  // that DefaultRefDeleter suffices in all cases.
109  template < class T >
111 
112 
113  // Special case for JNI-provided input parameters to native methods, which apparently
114  // should not be explicitly deleted (https://bugs.chromium.org/p/chromium/issues/detail?id=506850).
115  struct NullDeleter
116  {
117  NullDeleter() = default;
118  NullDeleter(JNIEnv&) {}
119  void operator()(jobject*) const {}
120  };
121 
122  template < class T >
124 
125 
126  template < class T >
128  {
129  using Type = T;
130  };
131 
132  template < class T, class D >
133  struct RemoveUnique< Unique<T, D> >
134  {
135  using Type = T;
136  };
137 
138  template < class T >
140 
141 
142  template < class T >
143  auto ReleaseUnique(T primitive)
144  {
145  return primitive;
146  }
147 
148  template < class T, class D >
150  {
151  return t.release();
152  }
153 
154 
155  template < template < RefDeletionMethod > class Deleter, class T >
156  auto NewGlobal(JNIEnv& env, const T& t)
157  {
158  return Global<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewGlobalRef(env, t.get()).release()));
159  }
160 
161  template < class T >
162  auto NewGlobal(JNIEnv& env, const T& t)
163  {
164  return NewGlobal<DefaultRefDeleter>(env, t);
165  }
166 
167  // Attempt to promote a weak reference to a strong one. Returns an empty result
168  // if the weak reference has expired.
169  //
170  // Beware that the semantics of JNI weak references are weaker than is typically
171  // desired: a JNI weak reference may still be promoted to a non-null strong reference
172  // even during finalization. Consider using jni::WeakReference<T> instead.
173  template < template < RefDeletionMethod > class Deleter, class T, template < RefDeletionMethod > class WeakDeleter >
175  {
176  jobject* obj = Wrap<jobject*>(env.NewGlobalRef(Unwrap(t->get())));
177  CheckJavaException(env);
178  return Global<T, Deleter>(env, obj);
179  }
180 
181  template < class T >
182  Global<T> NewGlobal(JNIEnv& env, const Weak<T>& t)
183  {
184  return NewGlobal<DefaultRefDeleter>(env, t);
185  }
186 
187 
188  template < template < RefDeletionMethod > class Deleter, class T >
189  auto NewWeak(JNIEnv& env, const T& t)
190  {
191  return Weak<RemoveUniqueType<T>, Deleter>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewWeakGlobalRef(env, t.get()).release()));
192  }
193 
194  template < class T >
195  auto NewWeak(JNIEnv& env, const T& t)
196  {
197  return NewWeak<DefaultRefDeleter>(env, t);
198  }
199 
200 
201  template < class T >
202  auto NewLocal(JNIEnv& env, const T& t)
203  {
204  return Local<RemoveUniqueType<T>>(env, reinterpret_cast<typename T::UntaggedType*>(jni::NewLocalRef(env, t.get()).release()));
205  }
206 
207  // Attempt to promote a weak reference to a strong one. Returns an empty result
208  // if the weak reference has expired.
209  //
210  // Beware that the semantics of JNI weak references are weaker than is typically
211  // desired: a JNI weak reference may still be promoted to a non-null strong reference
212  // even during finalization. Consider using jni::WeakReference<T> instead.
213  template < class T, template < RefDeletionMethod > class WeakDeleter >
214  Local<T> NewLocal(JNIEnv& env, const Weak<T, WeakDeleter>& t)
215  {
216  jobject* obj = Wrap<jobject*>(env.NewLocalRef(Unwrap(t->get())));
217  CheckJavaException(env);
218  return Local<T>(env, obj);
219  }
220  }
UniqueLocalRef< T > NewLocalRef(JNIEnv &env, T *t)
Definition: functions.hpp:172
decltype(Untag(std::declval< T >())) UntaggedType
Definition: tagging.hpp:130
T Type
Definition: unique.hpp:135
UniqueGlobalRef< T, Deleter > NewGlobalRef(JNIEnv &env, T *t)
Definition: functions.hpp:132
auto ReleaseUnique(T primitive)
Definition: unique.hpp:143
const D & get_deleter() const
Definition: unique.hpp:97
Unique(std::nullptr_t ptr=nullptr)
Definition: unique.hpp:50
Definition: errors.hpp:9
Unique(JNIEnv &env, UntaggedType *ptr)
Definition: unique.hpp:54
Definition: unique.hpp:127
Definition: unique.hpp:115
Definition: ownership.hpp:26
void operator()(jobject *) const
Definition: unique.hpp:119
D & get_deleter()
Definition: unique.hpp:96
Definition: advanced_ownership.hpp:5
Unique(Unique &&other)
Definition: unique.hpp:58
auto NewWeak(JNIEnv &env, const T &t)
Definition: unique.hpp:189
Unique & operator=(Unique &&other)
Definition: unique.hpp:72
auto Unwrap(W &&w)
Definition: wrapping.hpp:22
typename RemoveUnique< T >::Type RemoveUniqueType
Definition: unique.hpp:139
Unique(Unique< U, D > &&other, std::enable_if_t< std::is_convertible< const U &, const T &>::value > *=nullptr)
Definition: unique.hpp:63
UniqueWeakGlobalRef< T, Deleter > NewWeakGlobalRef(JNIEnv &env, T *t)
Definition: functions.hpp:205
Definition: unique.hpp:38
NullDeleter(JNIEnv &)
Definition: unique.hpp:118
R CheckJavaException(JNIEnv &env, R &&r)
Definition: errors.hpp:61
auto NewLocal(JNIEnv &env, const T &t)
Definition: unique.hpp:202
UntaggedType * release()
Definition: unique.hpp:89
~Unique()
Definition: unique.hpp:67
typename TagTraits< TheTag >::UntaggedType UntaggedType
Definition: object.hpp:49
void reset(UntaggedType *ptr=nullptr)
Definition: unique.hpp:79
T Type
Definition: unique.hpp:129
Definition: types.hpp:30
auto NewGlobal(JNIEnv &env, const T &t)
Definition: unique.hpp:156