Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-19 08:08:31

0001 // General object definitions: pointers, reference counting, garbage collection.
0002 
0003 #ifndef _CL_OBJECT_H
0004 #define _CL_OBJECT_H
0005 
0006 #include "cln/types.h"
0007 #include "cln/modules.h"
0008 #include <cstdlib>
0009 
0010 namespace cln {
0011 
0012 // We don't have to deal with circular structures, so normal reference counting
0013 // is sufficient. Is also has the advantage of being mostly non-interrupting.
0014 
0015 
0016 // An object is either a pointer to heap allocated data or immediate data.
0017 // It is possible to distinguish these because pointers are aligned.
0018 
0019 // Four basic classes are introduced:
0020 //
0021 //   gcobject      rcobject
0022 //
0023 //   gcpointer     rcpointer
0024 //
0025 // `gcobject' = garbage collectible object (pointer or immediate),
0026 // `gcpointer' = garbage collectible pointer,
0027 // `rcobject' = reference counted object (pointer or immediate),
0028 // `rcpointer' = reference counted pointer.
0029 //
0030 // "garbage collectible" means that a reference count is maintained, and
0031 // when the reference count drops to 0, the object is freed. This is useful
0032 // for all kind of short- or long-lived objects.
0033 // "reference counted" means that a reference count is maintained, which
0034 // cannot drop to 0. This is useful for objects which are registered in a
0035 // global cache table, in order to know which objects can be thrown away
0036 // when the cache is cleaned. (If the cache were never cleaned, its objects
0037 // would never be freed, and we could get away with normal C pointers.)
0038 //
0039 // It is permissible to treat a `rcobject' as a `gcobject', and a `rcpointer'
0040 // as a `gcpointer', but this just increases the destructor and copy-constructor
0041 // overhead.
0042 // It is also permissible to treat a `gcpointer' as a `gcobject', and a
0043 // `rcpointer' as a `rcobject', but this just increases the destructor and
0044 // copy-constructor overhead.
0045 
0046 
0047 // Immediate data is a word, as wide as a pointer.
0048 typedef sintP  cl_sint;
0049 typedef uintP  cl_uint;  // This ought to be called `cl_word'.
0050 #define cl_pointer_size intPsize
0051 // NB: (cl_pointer_size==64) implies defined(HAVE_FAST_LONGLONG)
0052 #if (cl_pointer_size==64)
0053   #define CL_WIDE_POINTERS
0054 #endif
0055 
0056 // Distinguish immediate data from pointers.
0057 inline bool cl_pointer_p (cl_uint word)
0058 {
0059     return (word & (cl_word_alignment-1)) == 0;
0060 }
0061 inline bool cl_immediate_p (cl_uint word)
0062 {
0063     return (word & (cl_word_alignment-1)) != 0;
0064 }
0065 
0066 // Immediate data: Fixnum, Short Float, maybe Single Float.
0067 // They have type tags.
0068 //   |...............................|......|
0069 //               cl_value             cl_tag
0070 
0071 // Number of bits reserved for tagging information:
0072 #if (cl_word_alignment <= 4)
0073   #define cl_tag_len    2
0074 #else
0075   #define cl_tag_len    3
0076 #endif
0077 #define cl_tag_shift    0
0078 #define cl_value_shift  (cl_tag_len+cl_tag_shift)
0079 #define cl_value_len    (cl_pointer_size - cl_value_shift)
0080 #define cl_tag_mask ((((cl_uint)1 << cl_tag_len) - 1) << cl_tag_shift)
0081 #define cl_value_mask   ((((cl_uint)1 << cl_value_len) - 1) << cl_value_shift)
0082 
0083 // Return the tag of a word.
0084 inline cl_uint cl_tag (cl_uint word)
0085 {
0086     return (word & cl_tag_mask) >> cl_tag_shift;
0087 }
0088 
0089 // Return the value (unsigned) of a word.
0090 inline cl_uint cl_value (cl_uint word)
0091 {
0092     // This assumes cl_value_shift + cl_value_len == cl_pointer_size.
0093     return word >> cl_value_shift;
0094 }
0095 
0096 // Return a word, combining a value and a tag.
0097 inline cl_uint cl_combine_impl (cl_uint tag, cl_uint value)
0098 {
0099     return (value << cl_value_shift) + (tag << cl_tag_shift);
0100 }
0101 inline cl_uint cl_combine_impl (cl_uint tag, cl_sint value)
0102 {
0103     // This assumes cl_value_shift + cl_value_len == cl_pointer_size.
0104     return (value << cl_value_shift) + (tag << cl_tag_shift);
0105 }
0106 inline cl_uint cl_combine (cl_uint tag, unsigned int value)
0107 { return cl_combine_impl(tag, (cl_uint)value); }
0108 inline cl_uint cl_combine (cl_uint tag, int value)
0109 { return cl_combine_impl(tag, (cl_sint)value); }
0110 inline cl_uint cl_combine (cl_uint tag, unsigned long value)
0111 { return cl_combine_impl(tag, (cl_uint)value); }
0112 inline cl_uint cl_combine (cl_uint tag, long value)
0113 { return cl_combine_impl(tag, (cl_sint)value); }
0114 inline cl_uint cl_combine (cl_uint tag, unsigned long long value)
0115 { return cl_combine_impl(tag, (cl_uint)value); }
0116 inline cl_uint cl_combine (cl_uint tag, long long value)
0117 { return cl_combine_impl(tag, (cl_uint)value); }
0118 
0119 // Definition of the tags.
0120 #if !defined(CL_WIDE_POINTERS)
0121   #if (cl_word_alignment == 2)
0122     #define cl_FN_tag   1
0123     #define cl_SF_tag   3   // must satisfy the cl_immediate_p predicate!
0124   #endif
0125   #if (cl_word_alignment == 4)
0126     #define cl_FN_tag   1
0127     #define cl_SF_tag   2
0128   #endif
0129 #else // CL_WIDE_POINTERS
0130   // Single Floats are immediate as well.
0131   #define cl_FN_tag 1
0132   #define cl_SF_tag 2
0133   #define cl_FF_tag 3
0134 #endif
0135 
0136 // Corresponding classes.
0137 extern const struct cl_class * cl_immediate_classes [1<<cl_tag_len];
0138 
0139 
0140 // Heap allocated data contains a header, for two purposes:
0141 // - dynamic typing,
0142 // - reference count (a portable alternative to garbage collection,
0143 //   or the basis for a portable and interoperable garbage collection).
0144 struct cl_heap {
0145     int refcount;           // reference count
0146     const struct cl_class * type;   // type tag
0147 };
0148 
0149 // Function to destroy the contents of a heap object.
0150 typedef void (*cl_heap_destructor_function) (cl_heap* pointer);
0151 // Flags, may be ORed together.
0152 #define cl_class_flags_subclass_complex   1  // all instances belong to cl_N
0153 #define cl_class_flags_subclass_real      2  // all instances belong to cl_R
0154 #define cl_class_flags_subclass_float     4  // all instances belong to cl_F
0155 #define cl_class_flags_subclass_rational  8  // all instances belong to cl_RA
0156 #define cl_class_flags_number_ring       16  // all instances are rings whose
0157                                              // elements belong to cl_number
0158 #define cl_class_flags_modint_ring       32  // all instances are rings whose
0159                                              // elements belong to cl_MI
0160 #define cl_class_flags_univpoly_ring     64  // all instances are rings whose
0161                                              // elements belong to cl_UP
0162 // Function to print an object for debugging, to cerr.
0163 typedef void (*cl_heap_dprint_function) (cl_heap* pointer);
0164 
0165 struct cl_class {
0166     cl_heap_destructor_function destruct;
0167     int flags;
0168     cl_heap_dprint_function dprint;
0169 };
0170 
0171 // Free an object on heap.
0172 extern void cl_free_heap_object (cl_heap* pointer);
0173 
0174 // Debugging support for dynamic typing: Register a debugging print function.
0175 #define cl_register_type_printer(type,printer)  \
0176   { extern cl_class type; type.dprint = (printer); }
0177 
0178 
0179 // cl_private_thing: An immediate value or a pointer into the heap.
0180 // This must be as wide as a `cl_uint'.
0181 // (Actually, this ought to be a  union { void*; cl_uint; }, but using
0182 // a pointer type generates better code.)
0183 // Never throw away a cl_private_thing, or reference counts will be wrong!
0184 typedef struct cl_anything * cl_private_thing;
0185 
0186 // Increment the reference count.
0187 inline void cl_inc_pointer_refcount (cl_heap* pointer)
0188 {
0189     pointer->refcount++;
0190 }
0191 
0192 // Decrement the reference count of a garbage collected pointer.
0193 inline void cl_gc_dec_pointer_refcount (cl_heap* pointer)
0194 {
0195     if (--pointer->refcount == 0)
0196         cl_free_heap_object(pointer);
0197 }
0198 // Decrement the reference count of a reference counted pointer.
0199 inline void cl_rc_dec_pointer_refcount (cl_heap* pointer)
0200 {
0201     --pointer->refcount;
0202 }
0203 
0204 // Increment the reference count.
0205 // This must be a macro, not an inline function, because pointer_p() and
0206 // inc_pointer_refcount() are non-virtual member functions, so that the
0207 // compiler can optimize it.
0208 #define cl_inc_refcount(x)  \
0209     if ((x).pointer_p())                    \
0210         (x).inc_pointer_refcount();         \
0211 
0212 // Decrement the reference count.
0213 // This must be a macro, not an inline function, because pointer_p() and
0214 // dec_pointer_refcount() are non-virtual member functions, so that the
0215 // compiler can optimize it.
0216 #define cl_dec_refcount(x)  \
0217     if ((x).pointer_p())                    \
0218         (x).dec_pointer_refcount();         \
0219 
0220 // The declaration of a copy constructor.
0221 // Restriction: The base class's default constructor must do nothing or
0222 // initialize `pointer' to a constant expression.
0223 #define CL_DEFINE_COPY_CONSTRUCTOR1(_class_)            \
0224     _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_class_)
0225 #define _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_classname_)   \
0226 inline _class_::_classname_ (const _class_& x)          \
0227 {                               \
0228     cl_uint x_word = x.word;                \
0229     cl_inc_refcount(x);                 \
0230     this->word = x_word;                    \
0231 }
0232 
0233 // The declaration of a copy constructor.
0234 // Restriction: The base class must have the usual `cl_private_thing'
0235 // constructor. Drawback: The base class must be known here.
0236 #define CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_baseclass_)        \
0237     _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_class_,_baseclass_)
0238 #define _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_classname_,_baseclass_) \
0239 inline _class_::_classname_ (const _class_& x)          \
0240     : _baseclass_ (as_cl_private_thing(x)) {}
0241 
0242 // The declaration of an assignment operator.
0243 #define CL_DEFINE_ASSIGNMENT_OPERATOR(dest_class,src_class) \
0244 inline dest_class& dest_class::operator= (const src_class& x)   \
0245 {                               \
0246     /* Be careful, we might be assigning x to itself. */    \
0247     cl_uint x_word = x.word;                \
0248     cl_inc_refcount(x);                 \
0249     cl_dec_refcount(*this);                 \
0250     this->word = x_word;                    \
0251     return *this;                       \
0252 }
0253 
0254 // We have a small problem with destructors: The specialized destructor
0255 // of a leaf class such as `cl_SF' should be more efficient than the
0256 // general destructor for `cl_N'. Since (by C++ specs) destructing a cl_SF
0257 // would run the destructors for cl_SF, cl_F, cl_R, cl_N (in that order),
0258 // and in the last step the compiler does not know any more that the object
0259 // actually is a cl_SF, there is no way to optimize the destructor!
0260 // ("progn-reversed" method combination is evil.)
0261 // And if we define "mirror"/"shadow" classes with no destructors (such
0262 // that `cl_F' inherits from `cl_F_no_destructor' buts adds a destructor)
0263 // then we need to add explicit conversion operators cl_SF -> cl_F -> cl_R ...,
0264 // with the effect that calling an overloaded function like `as_cl_F'
0265 // (which has two signatures `as_cl_F(cl_number)' and `as_cl_F(cl_F)')
0266 // with a cl_SF argument gives an "call of overloaded function is ambiguous"
0267 // error.
0268 // There is no help: If we want overloaded functions to be callable in a way
0269 // that makes sense, `cl_SF' has to be a subclass of `cl_F', and then the
0270 // destructor of `cl_SF' will do at least as much computation as the `cl_F'
0271 // destructor. Praise C++ ! :-((
0272 // (Even making `pointer_p()' a virtual function would not help.)
0273 
0274 
0275 // This is obnoxious.
0276 template <class key1_type, class value_type> struct cl_htentry1;
0277 
0278 // The four concrete classes of all objects.
0279 
0280 class cl_gcobject {
0281 public: /* ugh */
0282     union {
0283         void*   pointer;
0284         cl_heap* heappointer;
0285         cl_uint word;
0286     };
0287 public:
0288 // Default constructor. (Used for objects with no initializer.)
0289     cl_gcobject ();
0290 // Destructor. (Used when a variable goes out of scope.)
0291     ~cl_gcobject ();
0292 // Copy constructor.
0293     cl_gcobject (const cl_gcobject&);
0294 // Assignment operator.
0295     cl_gcobject& operator= (const cl_gcobject&);
0296 // Distinguish immediate data from pointer.
0297     bool pointer_p() const
0298         { return cl_pointer_p(word); }
0299 // Reference counting.
0300     void inc_pointer_refcount () const
0301         { cl_inc_pointer_refcount(heappointer); }
0302     void dec_pointer_refcount () const
0303         { cl_gc_dec_pointer_refcount(heappointer); }
0304 // Return the type tag of an immediate number.
0305     cl_uint nonpointer_tag () const
0306         { return cl_tag(word); }
0307 // Return the type tag of a heap-allocated number.
0308     const cl_class * pointer_type () const
0309         { return heappointer->type; }
0310 // Private pointer manipulations.
0311     cl_private_thing _as_cl_private_thing () const;
0312 // Private constructor.
0313     cl_gcobject (cl_private_thing p)
0314         : pointer (p) {}
0315 // Debugging output.
0316     void debug_print () const;
0317 // Ability to place an object at a given address.
0318     void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
0319     void* operator new (size_t size) { return ::operator new (size); }
0320 };
0321 inline cl_gcobject::cl_gcobject () {}
0322 inline cl_gcobject::~cl_gcobject () { cl_dec_refcount(*this); }
0323 CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcobject)
0324 CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcobject,cl_gcobject)
0325 
0326 class cl_gcpointer {
0327 public: /* ugh */
0328     union {
0329         void*   pointer;
0330         cl_heap* heappointer;
0331         cl_uint word;
0332     };
0333 public:
0334 // Default constructor. (Used for objects with no initializer.)
0335     cl_gcpointer ();
0336 // Destructor. (Used when a variable goes out of scope.)
0337     ~cl_gcpointer ();
0338 // Copy constructor.
0339     cl_gcpointer (const cl_gcpointer&);
0340 // Assignment operator.
0341     cl_gcpointer& operator= (const cl_gcpointer&);
0342 // Distinguish immediate data from pointer.
0343     bool pointer_p() const
0344         { return true; }
0345 // Reference counting.
0346     void inc_pointer_refcount () const
0347         { cl_inc_pointer_refcount(heappointer); }
0348     void dec_pointer_refcount () const
0349         { cl_gc_dec_pointer_refcount(heappointer); }
0350 // Return the type tag of an immediate number.
0351     cl_uint nonpointer_tag () const
0352         { return cl_tag(word); }
0353 // Return the type tag of a heap-allocated number.
0354     const cl_class * pointer_type () const
0355         { return heappointer->type; }
0356 // Private pointer manipulations.
0357     cl_private_thing _as_cl_private_thing () const;
0358 // Private constructor.
0359     cl_gcpointer (cl_private_thing p)
0360         : pointer (p) {}
0361 // Debugging output.
0362     void debug_print () const;
0363 // Ability to place an object at a given address.
0364     void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
0365     void* operator new (size_t size) { return ::operator new (size); }
0366 };
0367 inline cl_gcpointer::cl_gcpointer () {}
0368 inline cl_gcpointer::~cl_gcpointer () { cl_dec_refcount(*this); }
0369 CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcpointer)
0370 CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcpointer,cl_gcpointer)
0371 
0372 class cl_rcobject {
0373 public: /* ugh */
0374     union {
0375         void*   pointer;
0376         cl_heap* heappointer;
0377         cl_uint word;
0378     };
0379 public:
0380 // Default constructor. (Used for objects with no initializer.)
0381     cl_rcobject ();
0382 // Destructor. (Used when a variable goes out of scope.)
0383     ~cl_rcobject ();
0384 // Copy constructor.
0385     cl_rcobject (const cl_rcobject&);
0386 // Assignment operator.
0387     cl_rcobject& operator= (const cl_rcobject&);
0388 // Distinguish immediate data from pointer.
0389     bool pointer_p() const
0390         { return cl_pointer_p(word); }
0391 // Reference counting.
0392     void inc_pointer_refcount () const
0393         { cl_inc_pointer_refcount(heappointer); }
0394     void dec_pointer_refcount () const
0395         { cl_rc_dec_pointer_refcount(heappointer); }
0396 // Return the type tag of an immediate number.
0397     cl_uint nonpointer_tag () const
0398         { return cl_tag(word); }
0399 // Return the type tag of a heap-allocated number.
0400     const cl_class * pointer_type () const
0401         { return heappointer->type; }
0402 // Private pointer manipulations.
0403     cl_private_thing _as_cl_private_thing () const;
0404 // Private constructor.
0405     cl_rcobject (cl_private_thing p)
0406         : pointer (p) {}
0407 // Debugging output.
0408     void debug_print () const;
0409 // Ability to place an object at a given address.
0410     void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
0411     void* operator new (size_t size) { return ::operator new (size); }
0412 };
0413 inline cl_rcobject::cl_rcobject () {}
0414 inline cl_rcobject::~cl_rcobject () { cl_dec_refcount(*this); }
0415 CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcobject)
0416 CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcobject,cl_rcobject)
0417 
0418 class cl_rcpointer {
0419 public: /* ugh */
0420     union {
0421         void*   pointer;
0422         cl_heap* heappointer;
0423         cl_uint word;
0424     };
0425 public:
0426 // Default constructor. (Used for objects with no initializer.)
0427     cl_rcpointer ();
0428 // Destructor. (Used when a variable goes out of scope.)
0429     ~cl_rcpointer ();
0430 // Copy constructor.
0431     cl_rcpointer (const cl_rcpointer&);
0432 // Assignment operator.
0433     cl_rcpointer& operator= (const cl_rcpointer&);
0434 // Distinguish immediate data from pointer.
0435     bool pointer_p() const
0436         { return true; }
0437 // Reference counting.
0438     void inc_pointer_refcount () const
0439         { cl_inc_pointer_refcount(heappointer); }
0440     void dec_pointer_refcount () const
0441         { cl_rc_dec_pointer_refcount(heappointer); }
0442 // Return the type tag of an immediate number.
0443     cl_uint nonpointer_tag () const
0444         { return cl_tag(word); }
0445 // Return the type tag of a heap-allocated number.
0446     const cl_class * pointer_type () const
0447         { return heappointer->type; }
0448 // Private pointer manipulations.
0449     cl_private_thing _as_cl_private_thing () const;
0450 // Private constructor.
0451     cl_rcpointer (cl_private_thing p)
0452         : pointer (p) {}
0453 // Debugging output.
0454     void debug_print () const;
0455 // Ability to place an object at a given address.
0456     void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
0457     void* operator new (size_t size) { return ::operator new (size); }
0458 };
0459 inline cl_rcpointer::cl_rcpointer () {}
0460 inline cl_rcpointer::~cl_rcpointer () { cl_dec_refcount(*this); }
0461 CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcpointer)
0462 CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcpointer,cl_rcpointer)
0463 
0464 // Private pointer manipulations.
0465 
0466 inline cl_private_thing cl_gcobject::_as_cl_private_thing () const
0467 {
0468     cl_private_thing p = (cl_private_thing) pointer;
0469     cl_inc_refcount(*this);
0470     return p;
0471 }
0472 inline cl_private_thing as_cl_private_thing (const cl_gcobject& x)
0473 {
0474     return x._as_cl_private_thing();
0475 }
0476 
0477 inline cl_private_thing cl_gcpointer::_as_cl_private_thing () const
0478 {
0479     cl_private_thing p = (cl_private_thing) pointer;
0480     cl_inc_refcount(*this);
0481     return p;
0482 }
0483 inline cl_private_thing as_cl_private_thing (const cl_gcpointer& x)
0484 {
0485     return x._as_cl_private_thing();
0486 }
0487 
0488 inline cl_private_thing cl_rcobject::_as_cl_private_thing () const
0489 {
0490     cl_private_thing p = (cl_private_thing) pointer;
0491     cl_inc_refcount(*this);
0492     return p;
0493 }
0494 inline cl_private_thing as_cl_private_thing (const cl_rcobject& x)
0495 {
0496     return x._as_cl_private_thing();
0497 }
0498 
0499 inline cl_private_thing cl_rcpointer::_as_cl_private_thing () const
0500 {
0501     cl_private_thing p = (cl_private_thing) pointer;
0502     cl_inc_refcount(*this);
0503     return p;
0504 }
0505 inline cl_private_thing as_cl_private_thing (const cl_rcpointer& x)
0506 {
0507     return x._as_cl_private_thing();
0508 }
0509 
0510 // Note: When we define a function that returns a class object by value,
0511 // we normally return it as const value. The declarations
0512 //            T func (...);                    (A)
0513 // and
0514 //            const T func (...);              (B)
0515 // behave identically and generate identical code, except that the code
0516 //            func(...) = foo;
0517 // compiles fine with (A) but is an error (and yields a warning) with (B).
0518 // We want this warning.
0519 
0520 // Define a conversion operator from one object to another object of the
0521 // same size.
0522   #define CL_DEFINE_CONVERTER(target_class)  \
0523     operator const target_class & () const              \
0524     {                                   \
0525       int (*dummy1)(int assert1 [2*(sizeof(target_class)==sizeof(*this))-1]); (void)dummy1; \
0526       return * (const target_class *) (void*) this;         \
0527     }
0528 
0529 }  // namespace cln
0530 
0531 #endif /* _CL_OBJECT_H */