MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
jtie_tconv_idcache_impl.hpp
1 /*
2  Copyright 2010 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
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; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 /*
19  * jtie_tconv_idcache_impl.hpp
20  */
21 
22 #ifndef jtie_tconv_idcache_impl_hpp
23 #define jtie_tconv_idcache_impl_hpp
24 
25 #include <assert.h> // not using namespaces yet
26 #include <jni.h>
27 
28 //#include "helpers.hpp"
29 
30 // ---------------------------------------------------------------------------
31 // JNI field/method IDs access & caching
32 // ---------------------------------------------------------------------------
33 
34 #if 0 // XXX ddefines not used at this time
35 
36 // compilation flags
37 #define JTIE_NO_JNI_ID_CACHING 0
38 #define JTIE_WEAK_JNI_ID_CACHING 1
39 #define JTIE_STRONG_JNI_ID_CACHING 2
40 
41 #if !defined(JTIE_JNI_ID_CACHING)
42 # define JNI_ID_CACHING WEAK_CACHING
43 #elif (JTIE_JNI_ID_CACHING == JTIE_NO_JNI_ID_CACHING)
44 # define JNI_ID_CACHING NO_CACHING
45 #elif (JTIE_JNI_ID_CACHING == JTIE_WEAK_JNI_ID_CACHING)
46 # define JNI_ID_CACHING WEAK_CACHING
47 #elif (JTIE_JNI_ID_CACHING == JTIE_STRONG_JNI_ID_CACHING)
48 # define JNI_ID_CACHING STRONG_CACHING
49 #else
50 # error "Illegal value of JTIE_JNI_ID_CACHING"
51 #endif
52 
53 #endif // XXX ddefines not used at this time
54 
55 // ---------------------------------------------------------------------------
56 
57 // Local JNI helper functions
58 
59 template< typename T >
60 inline T
61 jniGetMemberID(JNIEnv * env,
62  jclass cls,
63  const char * name, const char * descriptor);
64 
65 template<>
66 inline jmethodID
67 jniGetMemberID< jmethodID >(JNIEnv * env,
68  jclass cls,
69  const char * name, const char * descriptor) {
70  return env->GetMethodID(cls, name, descriptor);
71 }
72 
73 template<>
74 inline jfieldID
75 jniGetMemberID< jfieldID >(JNIEnv * env,
76  jclass cls,
77  const char * name, const char * descriptor) {
78  return env->GetFieldID(cls, name, descriptor);
79 }
80 
81 // ---------------------------------------------------------------------------
82 
83 // XXX document these macros...
84 
88 #define JTIE_DEFINE_FIELD_MEMBER_INFO( T ) \
89  JTIE_DEFINE_CLASS_MEMBER_INFO( T, _jfieldID )
90 
94 #define JTIE_DEFINE_METHOD_MEMBER_INFO( T ) \
95  JTIE_DEFINE_CLASS_MEMBER_INFO( T, _jmethodID )
96 
100 #define JTIE_DEFINE_CLASS_MEMBER_INFO( T, IDT ) \
101  struct T { \
102  static const char * const class_name; \
103  static const char * const member_name; \
104  static const char * const member_descriptor; \
105  typedef IDT * memberID_t; \
106  };
107 
111 #define JTIE_INSTANTIATE_CLASS_MEMBER_INFO( T, CN, MN, MD ) \
112  const char * const T::class_name = CN; \
113  const char * const T::member_name = MN; \
114  const char * const T::member_descriptor = MD; \
115  template struct MemberId< T >; \
116  template struct MemberIdCache< T >;
117 
155 template< typename C >
156 struct MemberId {
157  typedef typename C::memberID_t ID_t;
158 
159  // number of JNI Get<Field|Method>ID() invocations for statistics
160  static unsigned long nIdLookUps;
161 
172  static void setClass(JNIEnv * env, jclass cls) {
173  assert(cls != NULL);
174  (void)env; (void)cls;
175  }
176 
196  static jclass getClass(JNIEnv * env) {
197  assert(env->ExceptionCheck() == JNI_OK);
198  jclass cls = env->FindClass(C::class_name);
199  if (cls == NULL) { // break out for better diagnostics
200  assert(env->ExceptionCheck() != JNI_OK); // exception pending
201 
202 //#ifndef NDEBUG // XXX for debugging
203  // print error diagnostics
204  char m[256];
205 #ifndef _WIN32
206  snprintf(m, 256, "JTie: failed to find Java class '%s'\n",
207 #else
208  _snprintf(m, 256, "JTie: failed to find Java class '%s'\n",
209 #endif
210  (C::class_name == NULL ? "NULL" : C::class_name));
211  fprintf(stderr, m);
212  env->ExceptionDescribe();
213  env->FatalError(m); // XXX for debugging
214 //#endif // NDEBUG
215  } else {
216  assert(env->ExceptionCheck() == JNI_OK); // ok
217  }
218  return cls;
219  }
220 
239  static ID_t getId(JNIEnv * env, jclass cls) {
240  assert(cls != NULL);
241  // multithreaded access ok, inaccurate if non-atomic increment
242  nIdLookUps++;
243  return jniGetMemberID< ID_t >(env, cls,
244  C::member_name, C::member_descriptor);
245  }
246 
254  static void releaseRef(JNIEnv * env, jclass cls) {
255  assert(cls != NULL);
256  env->DeleteLocalRef(cls);
257  }
258 };
259 
263 template< typename C >
264 struct MemberIdCache : MemberId< C > {
265  typedef typename C::memberID_t ID_t;
266 
267  static ID_t getId(JNIEnv * env, jclass cls) {
268  assert(cls != NULL);
269  // the cached member id is only valid along with global class ref
270  assert(env->IsSameObject(gClassRef, NULL) == JNI_FALSE);
271  (void)env; (void)cls;
272  return mid;
273  }
274 
275 protected:
276  // the cached global (weak or strong) class ref
277  static jclass gClassRef;
278 
279  // the cached member id (only valid along with global class ref)
280  static ID_t mid;
281 };
282 
287 template< typename C >
289  typedef MemberId< C > A;
290  typedef MemberIdCache< C > Base;
291 
292  static void setClass(JNIEnv * env, jclass cls) {
293  assert(cls != NULL);
294 
295  // multithreaded access ok, sets same class/member object
296  Base::gClassRef = static_cast< jclass >(env->NewWeakGlobalRef(cls));
297  Base::mid = A::getId(env, cls);
298  }
299 
300  using Base::getId; // use as inherited (some compiler wanted this)
301 
302  static jclass getClass(JNIEnv * env) {
303  // a weak global class ref may refer to a freed object at any time
304  // (i.e.: env->IsSameObject(Base::gClassRef, NULL))
305  // unless we've obtained a strong (local or global) non-NULL class ref
306  jclass cls = static_cast< jclass >(env->NewLocalRef(Base::gClassRef));
307  if (cls == NULL) {
308  // global class ref was NULL or referencing a freed object
309  cls = A::getClass(env);
310  if (cls == NULL) {
311  // exception pending
312  } else {
313  setClass(env, cls);
314  }
315  }
316  return cls;
317  }
318 
319  static void releaseRef(JNIEnv * env, jclass cls) {
320  assert(cls != NULL);
321  env->DeleteLocalRef(cls);
322  }
323 };
324 
329 template< typename C >
331  typedef MemberId< C > A;
332  typedef MemberIdCache< C > Base;
333 
334  static void setClass(JNIEnv * env, jclass cls) {
335  assert(cls != NULL);
336 
337  // multithreaded access ok, sets same class/member object
338  Base::gClassRef = static_cast< jclass >(env->NewGlobalRef(cls));
339  Base::mid = A::getId(env, cls);
340  }
341 
342  using Base::getId; // use as inherited (some compiler wanted this)
343 
344  static jclass getClass(JNIEnv * env) {
345  jclass cls = Base::gClassRef;
346  if (cls == NULL) {
347  cls = A::getClass(env);
348  if (cls == NULL) {
349  // exception pending
350  } else {
351  setClass(env, cls);
352  }
353  }
354  return cls;
355  }
356 
357  static void releaseRef(JNIEnv * env, jclass cls) {
358  assert(cls != NULL);
359  (void)env; (void)cls;
360  }
361 };
362 
367 template< typename C >
370 
371  using Base::setClass; // use as inherited (some compiler wanted this)
372 
373  using Base::getId; // use as inherited (some compiler wanted this)
374 
375  static jclass getClass(JNIEnv * env) {
376  // weak global class ref is assumed to be preloaded and valid
377  jclass cls = Base::gClassRef;
378  assert(env->IsSameObject(cls, NULL) == JNI_FALSE);
379  return cls;
380  }
381 
382  static void releaseRef(JNIEnv * env, jclass cls) {
383  assert(cls != NULL);
384  (void)env; (void)cls;
385  }
386 };
387 
392 template< typename C >
395 
396  using Base::setClass; // use as inherited (some compiler wanted this)
397 
398  using Base::getId; // use as inherited (some compiler wanted this)
399 
400  static jclass getClass(JNIEnv * env) {
401  // strong global class ref is assumed to be preloaded and valid
402  jclass cls = Base::gClassRef;
403  assert(env->IsSameObject(cls, NULL) == JNI_FALSE);
404  return cls;
405  }
406 
407  using Base::releaseRef; // use as inherited (some compiler wanted this)
408 };
409 
410 // XXX static initialization <-> multiple compilation units <-> jtie_lib.hpp
411 template< typename C > unsigned long MemberId< C >
412  ::nIdLookUps = 0;
413 
414 template< typename C > jclass MemberIdCache< C >
415  ::gClassRef = NULL;
416 
417 template< typename C > typename C::memberID_t MemberIdCache< C >
418  ::mid = NULL;
419 
420 // XXX document
421 
425 enum JniMemberIdCaching {
426  NO_CACHING
427  ,WEAK_CACHING
428  ,STRONG_CACHING
429 #if 0 // preloaded caching very tricky, not supported at this time
430  ,WEAK_CACHING_PRELOAD
431  ,STRONG_CACHING_PRELOAD
432 #endif // preloaded caching very tricky, not supported at this time
433 };
434 
438 template< JniMemberIdCaching M, typename C >
439 struct JniMemberId;
440 
441 template< typename C >
442 struct JniMemberId< NO_CACHING, C >
443  : MemberId< C > {};
444 
445 template< typename C >
446 struct JniMemberId< WEAK_CACHING, C >
447  : MemberIdWeakCache< C > {};
448 
449 template< typename C >
450 struct JniMemberId< STRONG_CACHING, C >
451  : MemberIdStrongCache< C > {};
452 
453 #if 0 // preloaded caching very tricky, not supported at this time
454 template< typename C >
455 struct JniMemberId< WEAK_CACHING_PRELOAD, C >
456  : MemberIdPreloadedWeakCache< C > {};
457 
458 template< typename C >
459 struct JniMemberId< STRONG_CACHING_PRELOAD, C >
461 #endif // preloaded caching very tricky, not supported at this time
462 
463 // ---------------------------------------------------------------------------
464 
465 #endif // jtie_tconv_idcache_impl_hpp