PageRenderTime 31ms CodeModel.GetById 21ms app.highlight 1ms RepoModel.GetById 0ms app.codeStats 0ms

/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 */