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