You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							563 lines
						
					
					
						
							19 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							563 lines
						
					
					
						
							19 KiB
						
					
					
				
								// General object definitions: pointers, reference counting, garbage collection.
							 | 
						|
								
							 | 
						|
								#ifndef _CL_OBJECT_H
							 | 
						|
								#define _CL_OBJECT_H
							 | 
						|
								
							 | 
						|
								#include "cln/types.h"
							 | 
						|
								#include "cln/modules.h"
							 | 
						|
								#include <cstdlib>
							 | 
						|
								
							 | 
						|
								namespace cln {
							 | 
						|
								
							 | 
						|
								// We don't have to deal with circular structures, so normal reference counting
							 | 
						|
								// is sufficient. Is also has the advantage of being mostly non-interrupting.
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// An object is either a pointer to heap allocated data
							 | 
						|
								//              or immediate data.
							 | 
						|
								
							 | 
						|
								// It is possible to distinguish these because pointers are aligned.
							 | 
						|
								// cl_uint_alignment is the guaranteed alignment of a `void*' or `long'
							 | 
						|
								// in memory. Must be > 1.
							 | 
						|
								#if defined(__m68k__)
							 | 
						|
								  #define cl_word_alignment  2
							 | 
						|
								#endif
							 | 
						|
								#if defined(__i386__) || defined(__mips__) || defined(__mipsel__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__hppa__) || defined(__arm__) || defined(__rs6000__) || defined(__m88k__) || defined(__convex__) || defined(__s390__)
							 | 
						|
								  #define cl_word_alignment  4
							 | 
						|
								#endif
							 | 
						|
								#if defined(__alpha__) || defined(__ia64__) || defined(__mips64__) || defined(__powerpc64__) || defined(__sparc64__) || defined(__x86_64__)
							 | 
						|
								  #define cl_word_alignment  8
							 | 
						|
								#endif
							 | 
						|
								#if !defined(cl_word_alignment)
							 | 
						|
								  #error "Define cl_word_alignment for your CPU!"
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// Four basic classes are introduced:
							 | 
						|
								//
							 | 
						|
								//   gcobject      rcobject
							 | 
						|
								//
							 | 
						|
								//   gcpointer     rcpointer
							 | 
						|
								//
							 | 
						|
								// `gcobject' = garbage collectible object (pointer or immediate),
							 | 
						|
								// `gcpointer' = garbage collectible pointer,
							 | 
						|
								// `rcobject' = reference counted object (pointer or immediate),
							 | 
						|
								// `rcpointer' = reference counted pointer.
							 | 
						|
								//
							 | 
						|
								// "garbage collectible" means that a reference count is maintained, and
							 | 
						|
								// when the reference count drops to 0, the object is freed. This is useful
							 | 
						|
								// for all kind of short- or long-lived objects.
							 | 
						|
								// "reference counted" means that a reference count is maintained, which
							 | 
						|
								// cannot drop to 0. This is useful for objects which are registered in a
							 | 
						|
								// global cache table, in order to know which objects can be thrown away
							 | 
						|
								// when the cache is cleaned. (If the cache were never cleaned, its objects
							 | 
						|
								// would never be freed, and we could get away with normal C pointers.)
							 | 
						|
								//
							 | 
						|
								// It is permissible to treat a `rcobject' as a `gcobject', and a `rcpointer'
							 | 
						|
								// as a `gcpointer', but this just increases the destructor and copy-constructor
							 | 
						|
								// overhead.
							 | 
						|
								// It is also permissible to treat a `gcpointer' as a `gcobject', and a
							 | 
						|
								// `rcpointer' as a `rcobject', but this just increases the destructor and
							 | 
						|
								// copy-constructor overhead.
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// Immediate data is a word, as wide as a pointer.
							 | 
						|
								typedef sintP  cl_sint;
							 | 
						|
								typedef uintP  cl_uint;  // This ought to be called `cl_word'.
							 | 
						|
								#define cl_pointer_size intPsize
							 | 
						|
								// NB: (cl_pointer_size==64) implies defined(HAVE_FAST_LONGLONG)
							 | 
						|
								#if (cl_pointer_size==64)
							 | 
						|
								  #define CL_WIDE_POINTERS
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								// Distinguish immediate data from pointers.
							 | 
						|
								inline bool cl_pointer_p (cl_uint word)
							 | 
						|
								{
							 | 
						|
									return (word & (cl_word_alignment-1)) == 0;
							 | 
						|
								}
							 | 
						|
								inline bool cl_immediate_p (cl_uint word)
							 | 
						|
								{
							 | 
						|
									return (word & (cl_word_alignment-1)) != 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Immediate data: Fixnum, Short Float, maybe Single Float.
							 | 
						|
								// They have type tags.
							 | 
						|
								//   |...............................|......|
							 | 
						|
								//               cl_value             cl_tag
							 | 
						|
								
							 | 
						|
								// Number of bits reserved for tagging information:
							 | 
						|
								#if (cl_word_alignment <= 4)
							 | 
						|
								  #define cl_tag_len	2
							 | 
						|
								#else
							 | 
						|
								  #define cl_tag_len	3
							 | 
						|
								#endif
							 | 
						|
								#define cl_tag_shift	0
							 | 
						|
								#define cl_value_shift  (cl_tag_len+cl_tag_shift)
							 | 
						|
								#define cl_value_len	(cl_pointer_size - cl_value_shift)
							 | 
						|
								#define cl_tag_mask	(((1UL << cl_tag_len) - 1) << cl_tag_shift)
							 | 
						|
								#define cl_value_mask	(((1UL << cl_value_len) - 1) << cl_value_shift)
							 | 
						|
								
							 | 
						|
								// Return the tag of a word.
							 | 
						|
								inline cl_uint cl_tag (cl_uint word)
							 | 
						|
								{
							 | 
						|
									return (word & cl_tag_mask) >> cl_tag_shift;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Return the value (unsigned) of a word.
							 | 
						|
								inline cl_uint cl_value (cl_uint word)
							 | 
						|
								{
							 | 
						|
									// This assumes cl_value_shift + cl_value_len == cl_pointer_size.
							 | 
						|
									return word >> cl_value_shift;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Return a word, combining a value and a tag.
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, cl_uint value)
							 | 
						|
								{
							 | 
						|
									return (value << cl_value_shift) + (tag << cl_tag_shift);
							 | 
						|
								}
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, cl_sint value)
							 | 
						|
								{
							 | 
						|
									// This assumes cl_value_shift + cl_value_len == cl_pointer_size.
							 | 
						|
									return (value << cl_value_shift) + (tag << cl_tag_shift);
							 | 
						|
								}
							 | 
						|
								// Keep the compiler happy.
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, unsigned int value)
							 | 
						|
								{ return cl_combine(tag, (cl_uint)value); }
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, int value)
							 | 
						|
								{ return cl_combine(tag, (cl_sint)value); }
							 | 
						|
								#ifdef HAVE_LONGLONG
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, unsigned long long value)
							 | 
						|
								{ return cl_combine(tag, (cl_uint)value); }
							 | 
						|
								inline cl_uint cl_combine (cl_uint tag, long long value)
							 | 
						|
								{ return cl_combine(tag, (cl_uint)value); }
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								// Definition of the tags.
							 | 
						|
								#if !defined(CL_WIDE_POINTERS)
							 | 
						|
								  #if (cl_word_alignment == 2)
							 | 
						|
								    #define cl_FN_tag	1
							 | 
						|
								    #define cl_SF_tag	3	// must satisfy the cl_immediate_p predicate!
							 | 
						|
								  #endif
							 | 
						|
								  #if (cl_word_alignment == 4)
							 | 
						|
								    #define cl_FN_tag	1
							 | 
						|
								    #define cl_SF_tag	2
							 | 
						|
								  #endif
							 | 
						|
								#else // CL_WIDE_POINTERS
							 | 
						|
								  // Single Floats are immediate as well.
							 | 
						|
								  #define cl_FN_tag	1
							 | 
						|
								  #define cl_SF_tag	2
							 | 
						|
								  #define cl_FF_tag	3
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								// Corresponding classes.
							 | 
						|
								extern const struct cl_class * cl_immediate_classes [1<<cl_tag_len];
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// Heap allocated data contains a header, for two purposes:
							 | 
						|
								// - dynamic typing,
							 | 
						|
								// - reference count (a portable alternative to garbage collection,
							 | 
						|
								//   or the basis for a portable and interoperable garbage collection).
							 | 
						|
								struct cl_heap {
							 | 
						|
									int refcount;			// reference count
							 | 
						|
									const struct cl_class * type;	// type tag
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// Function to destroy the contents of a heap object.
							 | 
						|
								typedef void (*cl_heap_destructor_function) (cl_heap* pointer);
							 | 
						|
								// Flags, may be ORed together.
							 | 
						|
								#define cl_class_flags_subclass_complex   1  // all instances belong to cl_N
							 | 
						|
								#define cl_class_flags_subclass_real      2  // all instances belong to cl_R
							 | 
						|
								#define cl_class_flags_subclass_float     4  // all instances belong to cl_F
							 | 
						|
								#define cl_class_flags_subclass_rational  8  // all instances belong to cl_RA
							 | 
						|
								#define cl_class_flags_number_ring       16  // all instances are rings whose
							 | 
						|
								                                             // elements belong to cl_number
							 | 
						|
								#define cl_class_flags_modint_ring       32  // all instances are rings whose
							 | 
						|
								                                             // elements belong to cl_MI
							 | 
						|
								#define cl_class_flags_univpoly_ring     64  // all instances are rings whose
							 | 
						|
								                                             // elements belong to cl_UP
							 | 
						|
								// Function to print an object for debugging, to cerr.
							 | 
						|
								typedef void (*cl_heap_dprint_function) (cl_heap* pointer);
							 | 
						|
								
							 | 
						|
								struct cl_class {
							 | 
						|
									cl_heap_destructor_function destruct;
							 | 
						|
									int flags;
							 | 
						|
									cl_heap_dprint_function dprint;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// Free an object on heap.
							 | 
						|
								extern void cl_free_heap_object (cl_heap* pointer);
							 | 
						|
								
							 | 
						|
								// Debugging support for dynamic typing: Register a debugging print function.
							 | 
						|
								#define cl_register_type_printer(type,printer)  \
							 | 
						|
								  { extern cl_class type; type.dprint = (printer); }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// cl_private_thing: An immediate value or a pointer into the heap.
							 | 
						|
								// This must be as wide as a `cl_uint'.
							 | 
						|
								// (Actually, this ought to be a  union { void*; cl_uint; }, but using
							 | 
						|
								// a pointer type generates better code.)
							 | 
						|
								// Never throw away a cl_private_thing, or reference counts will be wrong!
							 | 
						|
								typedef struct cl_anything * cl_private_thing;
							 | 
						|
								
							 | 
						|
								// Increment the reference count.
							 | 
						|
								inline void cl_inc_pointer_refcount (cl_heap* pointer)
							 | 
						|
								{
							 | 
						|
									pointer->refcount++;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Decrement the reference count of a garbage collected pointer.
							 | 
						|
								inline void cl_gc_dec_pointer_refcount (cl_heap* pointer)
							 | 
						|
								{
							 | 
						|
									if (--pointer->refcount == 0)
							 | 
						|
										cl_free_heap_object(pointer);
							 | 
						|
								}
							 | 
						|
								// Decrement the reference count of a reference counted pointer.
							 | 
						|
								inline void cl_rc_dec_pointer_refcount (cl_heap* pointer)
							 | 
						|
								{
							 | 
						|
									--pointer->refcount;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Increment the reference count.
							 | 
						|
								// This must be a macro, not an inline function, because pointer_p() and
							 | 
						|
								// inc_pointer_refcount() are non-virtual member functions, so that the
							 | 
						|
								// compiler can optimize it.
							 | 
						|
								#define cl_inc_refcount(x)  \
							 | 
						|
									if ((x).pointer_p())					\
							 | 
						|
										(x).inc_pointer_refcount();			\
							 | 
						|
								
							 | 
						|
								// Decrement the reference count.
							 | 
						|
								// This must be a macro, not an inline function, because pointer_p() and
							 | 
						|
								// dec_pointer_refcount() are non-virtual member functions, so that the
							 | 
						|
								// compiler can optimize it.
							 | 
						|
								#define cl_dec_refcount(x)  \
							 | 
						|
									if ((x).pointer_p())					\
							 | 
						|
										(x).dec_pointer_refcount();			\
							 | 
						|
								
							 | 
						|
								// The declaration of a copy constructor.
							 | 
						|
								// Restriction: The base class's default constructor must do nothing or
							 | 
						|
								// initialize `pointer' to a constant expression.
							 | 
						|
								#define CL_DEFINE_COPY_CONSTRUCTOR1(_class_)			\
							 | 
						|
									_CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_class_)
							 | 
						|
								#define _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_classname_)	\
							 | 
						|
								inline _class_::_classname_ (const _class_& x)			\
							 | 
						|
								{								\
							 | 
						|
									cl_uint x_word = x.word;				\
							 | 
						|
									cl_inc_refcount(x);					\
							 | 
						|
									this->word = x_word;					\
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// The declaration of a copy constructor.
							 | 
						|
								// Restriction: The base class must have the usual `cl_private_thing'
							 | 
						|
								// constructor. Drawback: The base class must be known here.
							 | 
						|
								#define CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_baseclass_)		\
							 | 
						|
									_CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_class_,_baseclass_)
							 | 
						|
								#define _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_classname_,_baseclass_) \
							 | 
						|
								inline _class_::_classname_ (const _class_& x)			\
							 | 
						|
									: _baseclass_ (as_cl_private_thing(x)) {}
							 | 
						|
								
							 | 
						|
								// The declaration of an assignment operator.
							 | 
						|
								#define CL_DEFINE_ASSIGNMENT_OPERATOR(dest_class,src_class)	\
							 | 
						|
								inline dest_class& dest_class::operator= (const src_class& x)	\
							 | 
						|
								{								\
							 | 
						|
									/* Be careful, we might be assigning x to itself. */	\
							 | 
						|
									cl_uint x_word = x.word;				\
							 | 
						|
									cl_inc_refcount(x);					\
							 | 
						|
									cl_dec_refcount(*this);					\
							 | 
						|
									this->word = x_word;					\
							 | 
						|
									return *this;						\
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// We have a small problem with destructors: The specialized destructor
							 | 
						|
								// of a leaf class such as `cl_SF' should be more efficient than the
							 | 
						|
								// general destructor for `cl_N'. Since (by C++ specs) destructing a cl_SF
							 | 
						|
								// would run the destructors for cl_SF, cl_F, cl_R, cl_N (in that order),
							 | 
						|
								// and in the last step the compiler does not know any more that the object
							 | 
						|
								// actually is a cl_SF, there is no way to optimize the destructor!
							 | 
						|
								// ("progn-reversed" method combination is evil.)
							 | 
						|
								// And if we define "mirror"/"shadow" classes with no destructors (such
							 | 
						|
								// that `cl_F' inherits from `cl_F_no_destructor' buts adds a destructor)
							 | 
						|
								// then we need to add explicit conversion operators cl_SF -> cl_F -> cl_R ...,
							 | 
						|
								// with the effect that calling an overloaded function like `as_cl_F'
							 | 
						|
								// (which has two signatures `as_cl_F(cl_number)' and `as_cl_F(cl_F)')
							 | 
						|
								// with a cl_SF argument gives an "call of overloaded function is ambiguous"
							 | 
						|
								// error.
							 | 
						|
								// There is no help: If we want overloaded functions to be callable in a way
							 | 
						|
								// that makes sense, `cl_SF' has to be a subclass of `cl_F', and then the
							 | 
						|
								// destructor of `cl_SF' will do at least as much computation as the `cl_F'
							 | 
						|
								// destructor. Praise C++ ! :-((
							 | 
						|
								// (Even making `pointer_p()' a virtual function would not help.)
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								// This is obnoxious.
							 | 
						|
								template <class key1_type, class value_type> struct cl_htentry1;
							 | 
						|
								
							 | 
						|
								// The four concrete classes of all objects.
							 | 
						|
								
							 | 
						|
								class cl_gcobject {
							 | 
						|
								public: /* ugh */
							 | 
						|
									union {
							 | 
						|
										void*   pointer;
							 | 
						|
										cl_heap* heappointer;
							 | 
						|
										cl_uint word;
							 | 
						|
									};
							 | 
						|
								public:
							 | 
						|
								// Default constructor. (Used for objects with no initializer.)
							 | 
						|
									cl_gcobject ();
							 | 
						|
								// Destructor. (Used when a variable goes out of scope.)
							 | 
						|
									~cl_gcobject ();
							 | 
						|
								// Copy constructor.
							 | 
						|
									cl_gcobject (const cl_gcobject&);
							 | 
						|
								// Assignment operator.
							 | 
						|
									cl_gcobject& operator= (const cl_gcobject&);
							 | 
						|
								// Distinguish immediate data from pointer.
							 | 
						|
									bool pointer_p() const
							 | 
						|
										{ return cl_pointer_p(word); }
							 | 
						|
								// Reference counting.
							 | 
						|
									void inc_pointer_refcount () const
							 | 
						|
										{ cl_inc_pointer_refcount(heappointer); }
							 | 
						|
									void dec_pointer_refcount () const
							 | 
						|
										{ cl_gc_dec_pointer_refcount(heappointer); }
							 | 
						|
								// Return the type tag of an immediate number.
							 | 
						|
									cl_uint nonpointer_tag () const
							 | 
						|
										{ return cl_tag(word); }
							 | 
						|
								// Return the type tag of a heap-allocated number.
							 | 
						|
									const cl_class * pointer_type () const
							 | 
						|
										{ return heappointer->type; }
							 | 
						|
								// Private pointer manipulations.
							 | 
						|
									cl_private_thing _as_cl_private_thing () const;
							 | 
						|
								// Private constructor.
							 | 
						|
									cl_gcobject (cl_private_thing p)
							 | 
						|
										#if !(defined(__alpha__) && !defined(__GNUC__))
							 | 
						|
										: pointer (p) {}
							 | 
						|
										#else
							 | 
						|
										{ pointer = p; }
							 | 
						|
										#endif
							 | 
						|
								// Debugging output.
							 | 
						|
									void debug_print () const;
							 | 
						|
								// Ability to place an object at a given address.
							 | 
						|
									void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
							 | 
						|
									void* operator new (size_t size) { return ::operator new (size); }
							 | 
						|
								};
							 | 
						|
								inline cl_gcobject::cl_gcobject () {}
							 | 
						|
								inline cl_gcobject::~cl_gcobject () { cl_dec_refcount(*this); }
							 | 
						|
								CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcobject)
							 | 
						|
								CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcobject,cl_gcobject)
							 | 
						|
								
							 | 
						|
								class cl_gcpointer {
							 | 
						|
								public: /* ugh */
							 | 
						|
									union {
							 | 
						|
										void*   pointer;
							 | 
						|
										cl_heap* heappointer;
							 | 
						|
										cl_uint word;
							 | 
						|
									};
							 | 
						|
								public:
							 | 
						|
								// Default constructor. (Used for objects with no initializer.)
							 | 
						|
									cl_gcpointer ();
							 | 
						|
								// Destructor. (Used when a variable goes out of scope.)
							 | 
						|
									~cl_gcpointer ();
							 | 
						|
								// Copy constructor.
							 | 
						|
									cl_gcpointer (const cl_gcpointer&);
							 | 
						|
								// Assignment operator.
							 | 
						|
									cl_gcpointer& operator= (const cl_gcpointer&);
							 | 
						|
								// Distinguish immediate data from pointer.
							 | 
						|
									bool pointer_p() const
							 | 
						|
										{ return true; }
							 | 
						|
								// Reference counting.
							 | 
						|
									void inc_pointer_refcount () const
							 | 
						|
										{ cl_inc_pointer_refcount(heappointer); }
							 | 
						|
									void dec_pointer_refcount () const
							 | 
						|
										{ cl_gc_dec_pointer_refcount(heappointer); }
							 | 
						|
								// Return the type tag of an immediate number.
							 | 
						|
									cl_uint nonpointer_tag () const
							 | 
						|
										{ return cl_tag(word); }
							 | 
						|
								// Return the type tag of a heap-allocated number.
							 | 
						|
									const cl_class * pointer_type () const
							 | 
						|
										{ return heappointer->type; }
							 | 
						|
								// Private pointer manipulations.
							 | 
						|
									cl_private_thing _as_cl_private_thing () const;
							 | 
						|
								// Private constructor.
							 | 
						|
									cl_gcpointer (cl_private_thing p)
							 | 
						|
										#if !(defined(__alpha__) && !defined(__GNUC__))
							 | 
						|
										: pointer (p) {}
							 | 
						|
										#else
							 | 
						|
										{ pointer = p; }
							 | 
						|
										#endif
							 | 
						|
								// Debugging output.
							 | 
						|
									void debug_print () const;
							 | 
						|
								// Ability to place an object at a given address.
							 | 
						|
									void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
							 | 
						|
									void* operator new (size_t size) { return ::operator new (size); }
							 | 
						|
								};
							 | 
						|
								inline cl_gcpointer::cl_gcpointer () {}
							 | 
						|
								inline cl_gcpointer::~cl_gcpointer () { cl_dec_refcount(*this); }
							 | 
						|
								CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcpointer)
							 | 
						|
								CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcpointer,cl_gcpointer)
							 | 
						|
								
							 | 
						|
								class cl_rcobject {
							 | 
						|
								public: /* ugh */
							 | 
						|
									union {
							 | 
						|
										void*   pointer;
							 | 
						|
										cl_heap* heappointer;
							 | 
						|
										cl_uint word;
							 | 
						|
									};
							 | 
						|
								public:
							 | 
						|
								// Default constructor. (Used for objects with no initializer.)
							 | 
						|
									cl_rcobject ();
							 | 
						|
								// Destructor. (Used when a variable goes out of scope.)
							 | 
						|
									~cl_rcobject ();
							 | 
						|
								// Copy constructor.
							 | 
						|
									cl_rcobject (const cl_rcobject&);
							 | 
						|
								// Assignment operator.
							 | 
						|
									cl_rcobject& operator= (const cl_rcobject&);
							 | 
						|
								// Distinguish immediate data from pointer.
							 | 
						|
									bool pointer_p() const
							 | 
						|
										{ return cl_pointer_p(word); }
							 | 
						|
								// Reference counting.
							 | 
						|
									void inc_pointer_refcount () const
							 | 
						|
										{ cl_inc_pointer_refcount(heappointer); }
							 | 
						|
									void dec_pointer_refcount () const
							 | 
						|
										{ cl_rc_dec_pointer_refcount(heappointer); }
							 | 
						|
								// Return the type tag of an immediate number.
							 | 
						|
									cl_uint nonpointer_tag () const
							 | 
						|
										{ return cl_tag(word); }
							 | 
						|
								// Return the type tag of a heap-allocated number.
							 | 
						|
									const cl_class * pointer_type () const
							 | 
						|
										{ return heappointer->type; }
							 | 
						|
								// Private pointer manipulations.
							 | 
						|
									cl_private_thing _as_cl_private_thing () const;
							 | 
						|
								// Private constructor.
							 | 
						|
									cl_rcobject (cl_private_thing p)
							 | 
						|
										#if !(defined(__alpha__) && !defined(__GNUC__))
							 | 
						|
										: pointer (p) {}
							 | 
						|
										#else
							 | 
						|
										{ pointer = p; }
							 | 
						|
										#endif
							 | 
						|
								// Debugging output.
							 | 
						|
									void debug_print () const;
							 | 
						|
								// Ability to place an object at a given address.
							 | 
						|
									void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
							 | 
						|
									void* operator new (size_t size) { return ::operator new (size); }
							 | 
						|
								};
							 | 
						|
								inline cl_rcobject::cl_rcobject () {}
							 | 
						|
								inline cl_rcobject::~cl_rcobject () { cl_dec_refcount(*this); }
							 | 
						|
								CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcobject)
							 | 
						|
								CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcobject,cl_rcobject)
							 | 
						|
								
							 | 
						|
								class cl_rcpointer {
							 | 
						|
								public: /* ugh */
							 | 
						|
									union {
							 | 
						|
										void*   pointer;
							 | 
						|
										cl_heap* heappointer;
							 | 
						|
										cl_uint word;
							 | 
						|
									};
							 | 
						|
								public:
							 | 
						|
								// Default constructor. (Used for objects with no initializer.)
							 | 
						|
									cl_rcpointer ();
							 | 
						|
								// Destructor. (Used when a variable goes out of scope.)
							 | 
						|
									~cl_rcpointer ();
							 | 
						|
								// Copy constructor.
							 | 
						|
									cl_rcpointer (const cl_rcpointer&);
							 | 
						|
								// Assignment operator.
							 | 
						|
									cl_rcpointer& operator= (const cl_rcpointer&);
							 | 
						|
								// Distinguish immediate data from pointer.
							 | 
						|
									bool pointer_p() const
							 | 
						|
										{ return true; }
							 | 
						|
								// Reference counting.
							 | 
						|
									void inc_pointer_refcount () const
							 | 
						|
										{ cl_inc_pointer_refcount(heappointer); }
							 | 
						|
									void dec_pointer_refcount () const
							 | 
						|
										{ cl_rc_dec_pointer_refcount(heappointer); }
							 | 
						|
								// Return the type tag of an immediate number.
							 | 
						|
									cl_uint nonpointer_tag () const
							 | 
						|
										{ return cl_tag(word); }
							 | 
						|
								// Return the type tag of a heap-allocated number.
							 | 
						|
									const cl_class * pointer_type () const
							 | 
						|
										{ return heappointer->type; }
							 | 
						|
								// Private pointer manipulations.
							 | 
						|
									cl_private_thing _as_cl_private_thing () const;
							 | 
						|
								// Private constructor.
							 | 
						|
									cl_rcpointer (cl_private_thing p)
							 | 
						|
										#if !(defined(__alpha__) && !defined(__GNUC__))
							 | 
						|
										: pointer (p) {}
							 | 
						|
										#else
							 | 
						|
										{ pointer = p; }
							 | 
						|
										#endif
							 | 
						|
								// Debugging output.
							 | 
						|
									void debug_print () const;
							 | 
						|
								// Ability to place an object at a given address.
							 | 
						|
									void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
							 | 
						|
									void* operator new (size_t size) { return ::operator new (size); }
							 | 
						|
								};
							 | 
						|
								inline cl_rcpointer::cl_rcpointer () {}
							 | 
						|
								inline cl_rcpointer::~cl_rcpointer () { cl_dec_refcount(*this); }
							 | 
						|
								CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcpointer)
							 | 
						|
								CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcpointer,cl_rcpointer)
							 | 
						|
								
							 | 
						|
								// Private pointer manipulations.
							 | 
						|
								
							 | 
						|
								inline cl_private_thing cl_gcobject::_as_cl_private_thing () const
							 | 
						|
								{
							 | 
						|
									cl_private_thing p = (cl_private_thing) pointer;
							 | 
						|
									cl_inc_refcount(*this);
							 | 
						|
									return p;
							 | 
						|
								}
							 | 
						|
								inline cl_private_thing as_cl_private_thing (const cl_gcobject& x)
							 | 
						|
								{
							 | 
						|
									return x._as_cl_private_thing();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								inline cl_private_thing cl_gcpointer::_as_cl_private_thing () const
							 | 
						|
								{
							 | 
						|
									cl_private_thing p = (cl_private_thing) pointer;
							 | 
						|
									cl_inc_refcount(*this);
							 | 
						|
									return p;
							 | 
						|
								}
							 | 
						|
								inline cl_private_thing as_cl_private_thing (const cl_gcpointer& x)
							 | 
						|
								{
							 | 
						|
									return x._as_cl_private_thing();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								inline cl_private_thing cl_rcobject::_as_cl_private_thing () const
							 | 
						|
								{
							 | 
						|
									cl_private_thing p = (cl_private_thing) pointer;
							 | 
						|
									cl_inc_refcount(*this);
							 | 
						|
									return p;
							 | 
						|
								}
							 | 
						|
								inline cl_private_thing as_cl_private_thing (const cl_rcobject& x)
							 | 
						|
								{
							 | 
						|
									return x._as_cl_private_thing();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								inline cl_private_thing cl_rcpointer::_as_cl_private_thing () const
							 | 
						|
								{
							 | 
						|
									cl_private_thing p = (cl_private_thing) pointer;
							 | 
						|
									cl_inc_refcount(*this);
							 | 
						|
									return p;
							 | 
						|
								}
							 | 
						|
								inline cl_private_thing as_cl_private_thing (const cl_rcpointer& x)
							 | 
						|
								{
							 | 
						|
									return x._as_cl_private_thing();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Note: When we define a function that returns a class object by value,
							 | 
						|
								// we normally return it as const value. The declarations
							 | 
						|
								//            T func (...);                    (A)
							 | 
						|
								// and
							 | 
						|
								//            const T func (...);              (B)
							 | 
						|
								// behave identically and generate identical code, except that the code
							 | 
						|
								//            func(...) = foo;
							 | 
						|
								// compiles fine with (A) but is an error (and yields a warning) with (B).
							 | 
						|
								// We want this warning.
							 | 
						|
								
							 | 
						|
								// Define a conversion operator from one object to another object of the
							 | 
						|
								// same size.
							 | 
						|
								  #define CL_DEFINE_CONVERTER(target_class)  \
							 | 
						|
								    operator const target_class & () const				\
							 | 
						|
								    {									\
							 | 
						|
								      typedef int assert1 [2*(sizeof(target_class)==sizeof(*this))-1];	\
							 | 
						|
								      return * (const target_class *) (void*) this;			\
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								}  // namespace cln
							 | 
						|
								
							 | 
						|
								#endif /* _CL_OBJECT_H */
							 |