/* -*- C++ -*- */ /*********************************************************************** * director.swg * * This file contains support for director classes that proxy * method calls from C++ to Ocaml extensions. * * Modified for Ocaml by : Art Yerkes * Original Author : Mark Rose (mrose@stm.lbl.gov) ************************************************************************/ #ifdef __cplusplus #include namespace Swig { /* base class for director exceptions */ class DirectorException { protected: std::string swig_msg; public: DirectorException(const char* msg="") { } const char *getMessage() const { return swig_msg.c_str(); } virtual ~DirectorException() {} }; /* type mismatch in the return value from a python method call */ class DirectorTypeMismatchException : public Swig::DirectorException { public: DirectorTypeMismatchException(const char* msg="") { } }; /* any python exception that occurs during a director method call */ class DirectorMethodException : public Swig::DirectorException {}; /* attempt to call a pure virtual method via a director method */ class DirectorPureVirtualException : public Swig::DirectorException {}; /* simple thread abstraction for pthreads on win32 */ #ifdef __THREAD__ #define __PTHREAD__ #if defined(_WIN32) || defined(__WIN32__) #define pthread_mutex_lock EnterCriticalSection #define pthread_mutex_unlock LeaveCriticalSection #define pthread_mutex_t CRITICAL_SECTION #define MUTEX_INIT(var) CRITICAL_SECTION var #else #include #define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER #endif #endif /* director base class */ class Director { private: /* pointer to the wrapped ocaml object */ CAML_VALUE swig_self; /* flag indicating whether the object is owned by ocaml or c++ */ mutable bool swig_disown_flag; mutable bool swig_up; #ifdef __PTHREAD__ /* locks for sharing the swig_up flag in a threaded environment */ static pthread_mutex_t swig_mutex_up; static bool swig_mutex_active; static pthread_t swig_mutex_thread; #endif /* reset the swig_up flag once the routing direction has been determined */ #ifdef __PTHREAD__ void swig_clear_up() const { swig_up = false; Swig::Director::swig_mutex_active = false; pthread_mutex_unlock(&swig_mutex_up); } #else void swig_clear_up() const { swig_up = false; } #endif public: /* wrap a ocaml object, optionally taking ownership */ Director(CAML_VALUE self, bool disown = false) : swig_self(self), swig_disown_flag(disown), swig_up( false ) { register_global_root(&swig_self); } /* discard our reference at destruction */ virtual ~Director() { remove_global_root(&swig_self); swig_disown(); // Disown is safe here because we're just divorcing a reference that // points to us. } /* return a pointer to the wrapped ocaml object */ CAML_VALUE swig_get_self() const { return swig_self; } /* get the swig_up flag to determine if the method call should be routed * to the c++ base class or through the wrapped ocaml object */ #ifdef __PTHREAD__ bool swig_get_up( bool clear = true ) const { if (Swig::Director::swig_mutex_active) { if (pthread_equal(Swig::Director::swig_mutex_thread, pthread_self())) { bool up = swig_up; if( clear ) swig_clear_up(); return up; } } return false; } #else bool swig_get_up( bool clear = true ) const { bool up = swig_up; if( clear ) swig_up = false; return up; } #endif /* set the swig_up flag if the next method call should be directed to * the c++ base class rather than the wrapped ocaml object */ #ifdef __PTHREAD__ void swig_set_up() const { pthread_mutex_lock(&Swig::Director::swig_mutex_up); Swig::Director::swig_mutex_thread = pthread_self(); Swig::Director::swig_mutex_active = true; swig_up = true; } #else void swig_set_up() const { swig_up = true; } #endif /* acquire ownership of the wrapped ocaml object (the sense of "disown" * is from ocaml) */ void swig_disown() const { if (!swig_disown_flag) { swig_disown_flag=true; callback(*caml_named_value("caml_obj_disown"),swig_self); } } }; #ifdef __PTHREAD__ MUTEX_INIT(Swig::Director::swig_mutex_up); pthread_t Swig::Director::swig_mutex_thread; bool Swig::Director::swig_mutex_active = false; #endif } #endif /* __cplusplus */