/tags/rel-1-3-29/SWIG/Lib/ocaml/director.swg
Unknown | 163 lines | 142 code | 21 blank | 0 comment | 0 complexity | a4b3ed47177fb81b5ccc86d376d33a55 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
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 Ocaml extensions. 9 * 10 * ----------------------------------------------------------------------------- */ 11 12#ifdef __cplusplus 13 14#include <string> 15 16namespace Swig { 17 /* base class for director exceptions */ 18 class DirectorException { 19 protected: 20 std::string swig_msg; 21 public: 22 DirectorException(const char* msg="") { 23 } 24 const char *getMessage() const { 25 return swig_msg.c_str(); 26 } 27 virtual ~DirectorException() {} 28 }; 29 30 /* type mismatch in the return value from a python method call */ 31 class DirectorTypeMismatchException : public Swig::DirectorException { 32 public: 33 DirectorTypeMismatchException(const char* msg="") { 34 } 35 }; 36 37 /* any python exception that occurs during a director method call */ 38 class DirectorMethodException : public Swig::DirectorException {}; 39 40 /* attempt to call a pure virtual method via a director method */ 41 class DirectorPureVirtualException : public Swig::DirectorException {}; 42 43 /* simple thread abstraction for pthreads on win32 */ 44#ifdef __THREAD__ 45#define __PTHREAD__ 46#if defined(_WIN32) || defined(__WIN32__) 47#define pthread_mutex_lock EnterCriticalSection 48#define pthread_mutex_unlock LeaveCriticalSection 49#define pthread_mutex_t CRITICAL_SECTION 50#define MUTEX_INIT(var) CRITICAL_SECTION var 51#else 52#include <pthread.h> 53#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER 54#endif 55#endif 56 57 /* director base class */ 58 class Director { 59 private: 60 /* pointer to the wrapped ocaml object */ 61 CAML_VALUE swig_self; 62 /* flag indicating whether the object is owned by ocaml or c++ */ 63 mutable bool swig_disown_flag; 64 mutable bool swig_up; 65 66#ifdef __PTHREAD__ 67 /* locks for sharing the swig_up flag in a threaded environment */ 68 static pthread_mutex_t swig_mutex_up; 69 static bool swig_mutex_active; 70 static pthread_t swig_mutex_thread; 71#endif 72 73 /* reset the swig_up flag once the routing direction has been determined */ 74#ifdef __PTHREAD__ 75 void swig_clear_up() const { 76 swig_up = false; 77 Swig::Director::swig_mutex_active = false; 78 pthread_mutex_unlock(&swig_mutex_up); 79 } 80 81#else 82 void swig_clear_up() const { 83 swig_up = false; 84 } 85#endif 86 87 public: 88 /* wrap a ocaml object, optionally taking ownership */ 89 Director(CAML_VALUE self) : swig_self(self), swig_disown_flag(false), swig_up( false ) { 90 register_global_root(&swig_self); 91 } 92 93 /* discard our reference at destruction */ 94 virtual ~Director() { 95 remove_global_root(&swig_self); 96 swig_disown(); 97 // Disown is safe here because we're just divorcing a reference that 98 // points to us. 99 } 100 101 /* return a pointer to the wrapped ocaml object */ 102 CAML_VALUE swig_get_self() const { 103 return swig_self; 104 } 105 106 /* get the swig_up flag to determine if the method call should be routed 107 * to the c++ base class or through the wrapped ocaml object 108 */ 109#ifdef __PTHREAD__ 110 bool swig_get_up( bool clear = true ) const { 111 if (Swig::Director::swig_mutex_active) { 112 if (pthread_equal(Swig::Director::swig_mutex_thread, pthread_self())) { 113 bool up = swig_up; 114 if( clear ) swig_clear_up(); 115 return up; 116 } 117 } 118 return false; 119 } 120 121#else 122 bool swig_get_up( bool clear = true ) const { 123 bool up = swig_up; 124 if( clear ) swig_up = false; 125 return up; 126 } 127#endif 128 129 /* set the swig_up flag if the next method call should be directed to 130 * the c++ base class rather than the wrapped ocaml object 131 */ 132#ifdef __PTHREAD__ 133 void swig_set_up() const { 134 pthread_mutex_lock(&Swig::Director::swig_mutex_up); 135 Swig::Director::swig_mutex_thread = pthread_self(); 136 Swig::Director::swig_mutex_active = true; 137 swig_up = true; 138 } 139#else 140 void swig_set_up() const { 141 swig_up = true; 142 } 143#endif 144 145 /* acquire ownership of the wrapped ocaml object (the sense of "disown" 146 * is from ocaml) */ 147 void swig_disown() const { 148 if (!swig_disown_flag) { 149 swig_disown_flag=true; 150 callback(*caml_named_value("caml_obj_disown"),swig_self); 151 } 152 } 153 }; 154 155#ifdef __PTHREAD__ 156 MUTEX_INIT(Swig::Director::swig_mutex_up); 157 pthread_t Swig::Director::swig_mutex_thread; 158 bool Swig::Director::swig_mutex_active = false; 159#endif 160 161} 162 163#endif /* __cplusplus */