Beatmup
objectpool.h
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <core/basic_types.h>
20 
21 #include "log.h"
22 
23 #include "java_factory.h"
24 
25 #include <mutex>
26 #include <vector>
27 #include <map>
28 #include <string>
29 
30 
31 /**
32  Handles all Java binding-related static data.
33 */
35 private:
36  std::multimap<const Beatmup::Object*, jobject> javaRefs; //!< Java global references representing dependencies of internal objects on external Java objects
37 
38  struct {
39  JNIEnv* env;
40  jfieldID handleFieldId;
42 
43 
44  /**
45  Java context check
46  */
47  inline bool queryJavaContext(JNIEnv* newEnv) {
48  if (javaContext.env == newEnv)
49  return true;
50  std::lock_guard<std::mutex> lock(access);
51  javaContext.env = newEnv;
52  jclass cls = newEnv->FindClass("Beatmup/Object");
53  javaContext.handleFieldId = newEnv->GetFieldID(cls, "handle", "J");
54  newEnv->DeleteLocalRef(cls);
55  return false;
56  }
57 
58  std::mutex access; //!< structure access control
59 
60 public:
62 
64 
65  /**
66  * Retrieves native object by its handle
67  */
68  template<class Object> inline Object* getObject(JNIEnv* jenv, jlong handle) {
69 #ifdef DEBUG_LOGGING
70  LOG_I("Hitting object #%lld", handle);
71 #endif
72  if (handle == INVALID_HANDLE)
73  return nullptr;
74  return static_cast<Object*>( (void*)handle );
75  }
76 
77  /**
78  * Retrieves native object from its Java prototype
79  */
80  template<class Object> inline Object* getObject(JNIEnv* jenv, jobject obj) {
82  if (!obj)
83  return nullptr;
84  jlong ptr = jenv->GetLongField(obj, javaContext.handleFieldId);
85 #ifdef DEBUG_LOGGING
86  LOG_I("Hitting object #%lld from Java", ptr);
87 #endif
88  if (ptr == INVALID_HANDLE)
89  return nullptr;
90  return static_cast<Object*>( (void*)jenv->GetLongField(obj, javaContext.handleFieldId) );
91  }
92 
93 
94  /**
95  * Sets a handle of a java object to null
96  */
97  void nullifyHandle(JNIEnv* jenv, jobject obj) {
99  jenv->SetLongField(obj, javaContext.handleFieldId, INVALID_HANDLE);
100  }
101 
102  /**
103  Creates new global reference on a Java object to avoid garbage collecting
104  */
105  void addJavaReference(JNIEnv* jenv, jobject jobj, const Beatmup::Object* bobj) {
106  std::lock_guard<std::mutex> lock(access);
107  javaRefs.insert(std::make_pair(bobj, jenv->NewGlobalRef(jobj)));
108  }
109 
110 
111  /**
112  Removes a Java reference
113  */
114  void removeJavaReference(JNIEnv* jenv, const Beatmup::Object* bobj) {
115  std::lock_guard<std::mutex> lock(access);
116  auto ref = javaRefs.find(bobj);
117  if (ref != javaRefs.end()) {
118  jenv->DeleteGlobalRef(ref->second);
119  javaRefs.erase(ref);
120  }
121  }
122 
123 
124  /**
125  Removes all Java references to depending objects
126  */
127  void removeAllJavaReferences(JNIEnv* jenv, const Beatmup::Object* bobj) {
128  std::lock_guard<std::mutex> lock(access);
129  while (true) {
130  auto ref = javaRefs.find(bobj);
131  if (ref == javaRefs.end())
132  break;
133  jenv->DeleteGlobalRef(ref->second);
134  javaRefs.erase(ref);
135  }
136  }
137 
138 
139  /**
140  Returns a reference to the Java object which a given object depends on.
141  */
143  return javaRefs.find(bobj)->second;
144  }
145 
146 
147 
149  javaContext.env = NULL;
150  }
151 
152 
153  /**
154  Throws a specific exception
155  */
156  static void throwToJava(JNIEnv* jenv, const char* exceptionClass, const char* message) {
157  jclass exClass = jenv->FindClass(exceptionClass);
158  jmethodID constructor = jenv->GetMethodID(exClass, "<init>", "(Ljava/lang/String;)V");
159  jobject exception = jenv->NewObject(exClass, constructor, jenv->NewStringUTF(message));
160  jenv->Throw((jthrowable) exception);
161  jenv->DeleteLocalRef(exClass);
162  }
163 
164 
165  /**
166  Throws a general exception
167  */
168  static void throwToJava(JNIEnv* jenv, const char* message) {
169  throwToJava(jenv, "Beatmup/Exceptions/CoreException", message);
170  }
171 
172 
173  /**
174  Rethrows a core-caused exception
175  */
176  static void rethrowToJava(JNIEnv* jenv, std::exception& ex) {
177  throwToJava(jenv, ex.what());
178  }
179 };
Handles all Java binding-related static data.
Definition: objectpool.h:34
void nullifyHandle(JNIEnv *jenv, jobject obj)
Sets a handle of a java object to null.
Definition: objectpool.h:97
static void throwToJava(JNIEnv *jenv, const char *exceptionClass, const char *message)
Throws a specific exception.
Definition: objectpool.h:156
static void throwToJava(JNIEnv *jenv, const char *message)
Throws a general exception.
Definition: objectpool.h:168
void addJavaReference(JNIEnv *jenv, jobject jobj, const Beatmup::Object *bobj)
Creates new global reference on a Java object to avoid garbage collecting.
Definition: objectpool.h:105
std::mutex access
structure access control
Definition: objectpool.h:58
jfieldID handleFieldId
Definition: objectpool.h:40
void removeAllJavaReferences(JNIEnv *jenv, const Beatmup::Object *bobj)
Removes all Java references to depending objects.
Definition: objectpool.h:127
Object * getObject(JNIEnv *jenv, jobject obj)
Retrieves native object from its Java prototype.
Definition: objectpool.h:80
static const jlong INVALID_HANDLE
Definition: objectpool.h:61
struct BeatmupJavaObjectPool::@20 javaContext
static void rethrowToJava(JNIEnv *jenv, std::exception &ex)
Rethrows a core-caused exception.
Definition: objectpool.h:176
bool queryJavaContext(JNIEnv *newEnv)
Java context check.
Definition: objectpool.h:47
jobject getJavaReference(const Beatmup::Object *bobj) const
Returns a reference to the Java object which a given object depends on.
Definition: objectpool.h:142
JavaFactory factory
Definition: objectpool.h:63
void removeJavaReference(JNIEnv *jenv, const Beatmup::Object *bobj)
Removes a Java reference.
Definition: objectpool.h:114
std::multimap< const Beatmup::Object *, jobject > javaRefs
Java global references representing dependencies of internal objects on external Java objects.
Definition: objectpool.h:36
Object * getObject(JNIEnv *jenv, jlong handle)
Retrieves native object by its handle.
Definition: objectpool.h:68
Beatmup object base class
Definition: basic_types.h:67
Set of utility functions for Java bindings.
Definition: java_factory.h:27
#define LOG_I(...)
Definition: log.h:23
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
JNIEnv jobject jlong handle
JNIEnv jclass
JNIEnv * jenv
JNIEnv jobject
return() jlong(listener)
jobject jobj