Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
5.7 KiB

  1. /* -----------------------------------------------------------------------------
  2. * See the LICENSE file for information on copyright, usage and redistribution
  3. * of SWIG, and the README file for authors - http://www.swig.org/release.html.
  4. *
  5. * director.swg
  6. *
  7. * This file contains support for director classes that proxy
  8. * method calls from C++ to Java extensions.
  9. * ----------------------------------------------------------------------------- */
  10. #ifdef __cplusplus
  11. #if defined(DEBUG_DIRECTOR_OWNED)
  12. #include <iostream>
  13. #endif
  14. namespace Swig {
  15. /* Java object wrapper */
  16. class JObjectWrapper {
  17. public:
  18. JObjectWrapper() : jthis_(NULL), weak_global_(true) {
  19. }
  20. ~JObjectWrapper() {
  21. jthis_ = NULL;
  22. weak_global_ = true;
  23. }
  24. bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
  25. if (!jthis_) {
  26. weak_global_ = weak_global;
  27. if (jobj)
  28. jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj));
  29. #if defined(DEBUG_DIRECTOR_OWNED)
  30. std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
  31. #endif
  32. return true;
  33. } else {
  34. #if defined(DEBUG_DIRECTOR_OWNED)
  35. std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
  36. #endif
  37. return false;
  38. }
  39. }
  40. jobject get(JNIEnv *jenv) const {
  41. #if defined(DEBUG_DIRECTOR_OWNED)
  42. std::cout << "JObjectWrapper::get(";
  43. if (jthis_)
  44. std::cout << jthis_;
  45. else
  46. std::cout << "null";
  47. std::cout << ") -> return new local ref" << std::endl;
  48. #endif
  49. return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
  50. }
  51. void release(JNIEnv *jenv) {
  52. #if defined(DEBUG_DIRECTOR_OWNED)
  53. std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl;
  54. #endif
  55. if (jthis_) {
  56. if (weak_global_) {
  57. if (jenv->IsSameObject(jthis_, NULL) == JNI_FALSE)
  58. jenv->DeleteWeakGlobalRef((jweak)jthis_);
  59. } else
  60. jenv->DeleteGlobalRef(jthis_);
  61. }
  62. jthis_ = NULL;
  63. weak_global_ = true;
  64. }
  65. jobject peek() {
  66. return jthis_;
  67. }
  68. /* Java proxy releases ownership of C++ object, C++ object is now
  69. responsible for destruction (creates NewGlobalRef to pin Java
  70. proxy) */
  71. void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
  72. if (take_or_release) { /* Java takes ownership of C++ object's lifetime. */
  73. if (!weak_global_) {
  74. jenv->DeleteGlobalRef(jthis_);
  75. jthis_ = jenv->NewWeakGlobalRef(jself);
  76. weak_global_ = true;
  77. }
  78. } else { /* Java releases ownership of C++ object's lifetime */
  79. if (weak_global_) {
  80. jenv->DeleteWeakGlobalRef((jweak)jthis_);
  81. jthis_ = jenv->NewGlobalRef(jself);
  82. weak_global_ = false;
  83. }
  84. }
  85. }
  86. private:
  87. /* pointer to Java object */
  88. jobject jthis_;
  89. /* Local or global reference flag */
  90. bool weak_global_;
  91. };
  92. /* director base class */
  93. class Director {
  94. /* pointer to Java virtual machine */
  95. JavaVM *swig_jvm_;
  96. protected:
  97. #if defined (_MSC_VER) && (_MSC_VER<1300)
  98. class JNIEnvWrapper;
  99. friend class JNIEnvWrapper;
  100. #endif
  101. /* Utility class for managing the JNI environment */
  102. class JNIEnvWrapper {
  103. const Director *director_;
  104. JNIEnv *jenv_;
  105. public:
  106. JNIEnvWrapper(const Director *director) : director_(director), jenv_(0) {
  107. director_->swig_jvm_->AttachCurrentThread((void **) &jenv_, NULL);
  108. }
  109. ~JNIEnvWrapper() {
  110. // Some JVMs, eg JDK 1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
  111. // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
  112. #if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
  113. director_->swig_jvm_->DetachCurrentThread();
  114. #endif
  115. }
  116. JNIEnv *getJNIEnv() const {
  117. return jenv_;
  118. }
  119. };
  120. /* Java object wrapper */
  121. JObjectWrapper swig_self_;
  122. /* Disconnect director from Java object */
  123. void swig_disconnect_director_self(const char *disconn_method) {
  124. JNIEnvWrapper jnienv(this) ;
  125. JNIEnv *jenv = jnienv.getJNIEnv() ;
  126. jobject jobj = swig_self_.peek();
  127. #if defined(DEBUG_DIRECTOR_OWNED)
  128. std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
  129. #endif
  130. if (jobj && jenv->IsSameObject(jobj, NULL) == JNI_FALSE) {
  131. jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
  132. if (disconn_meth) {
  133. #if defined(DEBUG_DIRECTOR_OWNED)
  134. std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl;
  135. #endif
  136. jenv->CallVoidMethod(jobj, disconn_meth);
  137. }
  138. }
  139. }
  140. public:
  141. Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() {
  142. /* Acquire the Java VM pointer */
  143. jenv->GetJavaVM(&swig_jvm_);
  144. }
  145. virtual ~Director() {
  146. JNIEnvWrapper jnienv(this) ;
  147. JNIEnv *jenv = jnienv.getJNIEnv() ;
  148. swig_self_.release(jenv);
  149. }
  150. bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
  151. return swig_self_.set(jenv, jself, mem_own, weak_global);
  152. }
  153. jobject swig_get_self(JNIEnv *jenv) const {
  154. return swig_self_.get(jenv);
  155. }
  156. // Change C++ object's ownership, relative to Java
  157. void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
  158. swig_self_.java_change_ownership(jenv, jself, take_or_release);
  159. }
  160. };
  161. }
  162. #endif /* __cplusplus */