Home | History | Annotate | Download | only in ruby
      1 /* -----------------------------------------------------------------------------
      2  * rubytracking.swg
      3  *
      4  * This file contains support for tracking mappings from
      5  * Ruby objects to C++ objects.  This functionality is needed
      6  * to implement mark functions for Ruby's mark and sweep
      7  * garbage collector.
      8  * ----------------------------------------------------------------------------- */
      9 
     10 #ifdef __cplusplus
     11 extern "C" {
     12 #endif
     13 
     14 /* Ruby 1.8 actually assumes the first case. */
     15 #if SIZEOF_VOIDP == SIZEOF_LONG
     16 #  define SWIG2NUM(v) LONG2NUM((unsigned long)v)
     17 #  define NUM2SWIG(x) (unsigned long)NUM2LONG(x)
     18 #elif SIZEOF_VOIDP == SIZEOF_LONG_LONG
     19 #  define SWIG2NUM(v) LL2NUM((unsigned long long)v)
     20 #  define NUM2SWIG(x) (unsigned long long)NUM2LL(x)
     21 #else
     22 #  error sizeof(void*) is not the same as long or long long
     23 #endif
     24 
     25 
     26 /* Global Ruby hash table to store Trackings from C/C++
     27    structs to Ruby Objects.
     28 */
     29 static VALUE swig_ruby_trackings = Qnil;
     30 
     31 /* Global variable that stores a reference to the ruby
     32    hash table delete function. */
     33 static ID swig_ruby_hash_delete;
     34 
     35 /* Setup a Ruby hash table to store Trackings */
     36 SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) {
     37   /* Create a ruby hash table to store Trackings from C++
     38      objects to Ruby objects. */
     39 
     40   /* Try to see if some other .so has already created a
     41      tracking hash table, which we keep hidden in an instance var
     42      in the SWIG module.
     43      This is done to allow multiple DSOs to share the same
     44      tracking table.
     45   */
     46   ID trackings_id = rb_intern( "@__trackings__" );
     47   VALUE verbose = rb_gv_get("VERBOSE");
     48   rb_gv_set("VERBOSE", Qfalse);
     49   swig_ruby_trackings = rb_ivar_get( _mSWIG, trackings_id );
     50   rb_gv_set("VERBOSE", verbose);
     51 
     52   /* No, it hasn't.  Create one ourselves */
     53   if ( swig_ruby_trackings == Qnil )
     54     {
     55       swig_ruby_trackings = rb_hash_new();
     56       rb_ivar_set( _mSWIG, trackings_id, swig_ruby_trackings );
     57     }
     58 
     59   /* Now store a reference to the hash table delete function
     60      so that we only have to look it up once.*/
     61   swig_ruby_hash_delete = rb_intern("delete");
     62 }
     63 
     64 /* Get a Ruby number to reference a pointer */
     65 SWIGRUNTIME VALUE SWIG_RubyPtrToReference(void* ptr) {
     66   /* We cast the pointer to an unsigned long
     67      and then store a reference to it using
     68      a Ruby number object. */
     69 
     70   /* Convert the pointer to a Ruby number */
     71   return SWIG2NUM(ptr);
     72 }
     73 
     74 /* Get a Ruby number to reference an object */
     75 SWIGRUNTIME VALUE SWIG_RubyObjectToReference(VALUE object) {
     76   /* We cast the object to an unsigned long
     77      and then store a reference to it using
     78      a Ruby number object. */
     79 
     80   /* Convert the Object to a Ruby number */
     81   return SWIG2NUM(object);
     82 }
     83 
     84 /* Get a Ruby object from a previously stored reference */
     85 SWIGRUNTIME VALUE SWIG_RubyReferenceToObject(VALUE reference) {
     86   /* The provided Ruby number object is a reference
     87      to the Ruby object we want.*/
     88 
     89   /* Convert the Ruby number to a Ruby object */
     90   return NUM2SWIG(reference);
     91 }
     92 
     93 /* Add a Tracking from a C/C++ struct to a Ruby object */
     94 SWIGRUNTIME void SWIG_RubyAddTracking(void* ptr, VALUE object) {
     95   /* In a Ruby hash table we store the pointer and
     96      the associated Ruby object.  The trick here is
     97      that we cannot store the Ruby object directly - if
     98      we do then it cannot be garbage collected.  So
     99      instead we typecast it as a unsigned long and
    100      convert it to a Ruby number object.*/
    101 
    102   /* Get a reference to the pointer as a Ruby number */
    103   VALUE key = SWIG_RubyPtrToReference(ptr);
    104 
    105   /* Get a reference to the Ruby object as a Ruby number */
    106   VALUE value = SWIG_RubyObjectToReference(object);
    107 
    108   /* Store the mapping to the global hash table. */
    109   rb_hash_aset(swig_ruby_trackings, key, value);
    110 }
    111 
    112 /* Get the Ruby object that owns the specified C/C++ struct */
    113 SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) {
    114   /* Get a reference to the pointer as a Ruby number */
    115   VALUE key = SWIG_RubyPtrToReference(ptr);
    116 
    117   /* Now lookup the value stored in the global hash table */
    118   VALUE value = rb_hash_aref(swig_ruby_trackings, key);
    119 
    120   if (value == Qnil) {
    121     /* No object exists - return nil. */
    122     return Qnil;
    123   }
    124   else {
    125     /* Convert this value to Ruby object */
    126     return SWIG_RubyReferenceToObject(value);
    127   }
    128 }
    129 
    130 /* Remove a Tracking from a C/C++ struct to a Ruby object.  It
    131    is very important to remove objects once they are destroyed
    132    since the same memory address may be reused later to create
    133    a new object. */
    134 SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) {
    135   /* Get a reference to the pointer as a Ruby number */
    136   VALUE key = SWIG_RubyPtrToReference(ptr);
    137 
    138   /* Delete the object from the hash table by calling Ruby's
    139      do this we need to call the Hash.delete method.*/
    140   rb_funcall(swig_ruby_trackings, swig_ruby_hash_delete, 1, key);
    141 }
    142 
    143 /* This is a helper method that unlinks a Ruby object from its
    144    underlying C++ object.  This is needed if the lifetime of the
    145    Ruby object is longer than the C++ object */
    146 SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) {
    147   VALUE object = SWIG_RubyInstanceFor(ptr);
    148 
    149   if (object != Qnil) {
    150     DATA_PTR(object) = 0;
    151   }
    152 }
    153 
    154 
    155 #ifdef __cplusplus
    156 }
    157 #endif
    158