Remove exception hooks in favor of real C++ exceptions:
* include/cln/exception.h: New file...
* include/cln/cln.h: ...included here...
* include/cln/rational.h: ...and here.
* include/cln/abort.h: Removed.
* include/cln/integer.h (ash_exception, exquo_exception): Add exception
types.
* include/cln/float.h (floating_point_exception,
floating_point_nan_exception, floating_point_overflow_exception,
floating_point_underflow_exception): Likewise.
* include/cln/number_io.h (read_number_exception,
read_number_bad_syntax_exception, read_number_junk_exception,
read_number_eof_exception): Likewise.
* include/cln/object.h (CL_DEFINE_CONVERTER): Replace dynamic assertion
with a compile-time assertion.
* include/cln/GV.h: Replace nonreturning functions with exceptions.
* include/cln/modinteger.h: Likewise.
* include/cln/SV.h: Likewise.
* include/cln/ring.h: Likewise.
* include/cln/string.h: Likewise.
* include/cln/univpoly.h: Likewise.
* src/base/cl_abort.cc: Removed.
* src/base/cl_N_err_d0.cc: Removed.
* src/base/cl_d0_exception.cc: New file.
* src/base/cl_as_err.cc: Removed.
* src/base/cl_as_exception.cc: New file.
* src/base/cl_notreached.cc: Removed.
* src/base/cl_notreached_exception.cc: New file.
* src/base/input/cl_read_err_bad.cc: Removed.
* src/base/input/cl_read_bad_syntax_exception.cc: New file.
* src/base/input/cl_read_err_junk.cc: Removed.
* src/base/input/cl_read_junk_exception.cc: New file.
* src/base/input/cl_read_err_eof.cc: Removed.
* src/base/input/cl_read_eof_exception.cc: New file.
* src/base/cl_N.h (cl_as_error): Removed (see cln/exception.h).
* src/base/macros.h (NOTREACHED): Throw.
* src/base/cl_malloc.cc (xmalloc): Throw.
* src/base/digitseq/cl_2DS_div.cc: Throw.
* src/base/digitseq/cl_DS_div.cc: Throw.
* src/base/digitseq/cl_DS_mul.cc: Throw.
* src/base/digitseq/cl_DS_mul_fftc.h: Throw.
* src/base/digitseq/cl_DS_mul_fftcs.h: Throw.
* src/base/digitseq/cl_DS_mul_fftm.h: Throw.
* src/base/digitseq/cl_DS_mul_fftp.h: Throw.
* src/base/digitseq/cl_DS_mul_fftp3.h: Throw.
* src/base/digitseq/cl_DS_mul_fftp3m.h: Throw.
* src/base/digitseq/cl_DS_mul_fftr.h: Throw.
* src/base/digitseq/cl_DS_mul_nuss.h: Throw.
* src/base/digitseq/cl_DS_recipsqrt.cc: Throw.
* src/base/digitseq/cl_DS_sqrt.cc: Throw.
* src/base/hash/cl_hash.h: Throw.
* src/base/hash/cl_hash1.h: Throw.
* src/base/hash/cl_hash1weak.h: Throw.
* src/base/hash/cl_hash2.h: Throw.
* src/base/hash/cl_hash2weak.h: Throw.
* src/base/hash/cl_hashset.h: Throw.
* src/base/hash/cl_hashuniq.h: Throw.
* src/base/hash/cl_hashuniqweak.h: Throw.
* src/base/proplist/cl_pl_add.cc: Throw.
* src/base/ring/cl_no_ring.cc: Throw.
* src/base/string/cl_spushstring.h: Throw.
* src/base/symbol/cl_symbol.cc: Throw.
* src/integer/bitwise/cl_I_ash.h: Removed (see cln/integer.h.)
* src/integer/bitwise/cl_I_asherr.cc: Removed.
* src/integer/bitwise/cl_I_ash_exception.cc: New file.
* src/integer/division/cl_I_exquoerr.cc: Removed.
* src/integer/division/cl_I_exquo_exception.cc: New file.
* src/integer/cl_I.h: Throw.
* src/integer/division/cl_I_exquopos.cc: Throw.
* src/integer/bitwise/cl_I_logbitp_I.cc: Throw.
* src/integer/bitwise/cl_I_ash.cc: Throw.
* src/integer/bitwise/cl_I_ash_I.cc: Throw.
* src/integer/division/cl_I_exquo.cc: Throw.
* src/integer/gcd/cl_I_gcd_aux2.cc: Throw.
* src/integer/conv/cl_I_to_L.cc: Throw.
* src/integer/conv/cl_I_to_Q.cc: Throw.
* src/integer/conv/cl_I_to_UL.cc: Throw.
* src/integer/conv/cl_I_to_UQ.cc: Throw.
* src/integer/conv/cl_I_to_digits.cc: Throw.
* src/integer/elem/cl_I_div.cc: Throw.
* src/integer/algebraic/cl_I_sqrt.cc: Throw.
* src/integer/input/cl_I_read.cc: Throw.
* src/integer/input/cl_I_read_stream.cc: Throw.
* src/integer/misc/cl_I_as.cc: Throw.
* src/rational/elem/cl_RA_from_I_I_div.cc: Throw.
* src/rational/elem/cl_RA_recip.cc: Throw.
* src/rational/input/cl_RA_read.cc: Throw.
* src/rational/input/cl_RA_read_stream.cc: Throw.
* src/rational/input/cl_RA_readparsed.cc: Throw.
* src/rational/misc/cl_RA_as.cc: Throw.
* src/float/base/cl_F_err_nan.cc: Removed.
* src/float/base/cl_F_nan_exception.cc: New file.
* src/float/base/cl_F_err_un.cc: Removed.
* src/float/base/cl_F_underflow_exception.cc: New file.
* src/float/base/cl_F_err_ov.cc: Removed.
* src/float/base/cl_F_overflow_exception.cc: New file.
* src/float/cl_F.h (cl_error_floating_point_nan,
cl_error_floating_point_overflow, cl_error_floating_point_underflow):
Removed (see cln/float.h.)
* src/float/sfloat/cl_SF.h: Throw.
* src/float/sfloat/elem/cl_SF_div.cc: Throw.
* src/float/sfloat/elem/cl_SF_from_RA.cc: Throw.
* src/float/sfloat/elem/cl_SF_scale.cc: Throw.
* src/float/sfloat/elem/cl_SF_scale_I.cc: Throw.
* src/float/sfloat/misc/cl_SF_as.cc: Throw.
* src/float/ffloat/cl_FF.h: Throw.
* src/float/ffloat/conv/cl_FF_from_float.cc: Throw.
* src/float/ffloat/elem/cl_FF_div.cc: Throw.
* src/float/ffloat/elem/cl_FF_from_RA.cc: Throw.
* src/float/ffloat/elem/cl_FF_scale.cc: Throw.
* src/float/ffloat/elem/cl_FF_scale_I.cc: Throw.
* src/float/ffloat/misc/cl_FF_as.cc: Throw.
* src/float/dfloat/cl_DF.h: Throw.
* src/float/dfloat/conv/cl_DF_from_double.cc: Throw.
* src/float/dfloat/elem/cl_DF_div.cc: Throw.
* src/float/dfloat/elem/cl_DF_from_RA.cc: Throw.
* src/float/dfloat/elem/cl_DF_scale.cc: Throw.
* src/float/dfloat/elem/cl_DF_scale_I.cc: Throw.
* src/float/dfloat/misc/cl_DF_as.cc: Throw.
* src/float/lfloat/algebraic/cl_LF_sqrt.cc: Throw.
* src/float/lfloat/elem/cl_LF_1plus.cc: Throw.
* src/float/lfloat/elem/cl_LF_I_div.cc: Throw.
* src/float/lfloat/elem/cl_LF_I_mul.cc: Throw.
* src/float/lfloat/elem/cl_LF_div.cc: Throw.
* src/float/lfloat/elem/cl_LF_from_I.cc: Throw.
* src/float/lfloat/elem/cl_LF_mul.cc: Throw.
* src/float/lfloat/elem/cl_LF_scale.cc: Throw.
* src/float/lfloat/elem/cl_LF_scale_I.cc: Throw.
* src/float/lfloat/elem/cl_LF_square.cc: Throw.
* src/float/lfloat/misc/cl_LF_as.cc: Throw.
* src/float/lfloat/misc/cl_LF_shorten.cc: Throw.
* src/float/lfloat/misc/cl_LF_shortenrel.cc: Throw.
* src/float/lfloat/misc/cl_LF_shortenwith.cc: Throw.
* src/float/input/cl_F_read.cc: Throw.
* src/float/input/cl_F_read_stream.cc: Throw.
* src/float/misc/cl_F_as.cc: Throw.
* src/float/misc/cl_F_shortenrel.cc: Throw.
* src/float/transcendental/cl_LF_coshsinh_aux.cc: Throw.
* src/float/transcendental/cl_LF_cossin_aux.cc: Throw.
* src/float/transcendental/cl_LF_exp_aux.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_a.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_ab.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_b.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_p.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pa.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pab.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pb.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pq.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pqa.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pqab.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_pqb.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_q.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_qa.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_qab.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_qb.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_stream_pq.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_stream_pqa.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_stream_pqab.cc: Throw.
* src/float/transcendental/cl_LF_ratseries_stream_pqb.cc: Throw.
* src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc: Throw.
* src/float/transcendental/cl_LF_ratsumseries_pqd.cc: Throw.
* src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc: Throw.
* src/float/transcendental/cl_LF_zeta_int.cc: Throw.
* src/real/elem/cl_R_div.cc: Throw.
* src/real/format-output/cl_fmt_cardinal.cc: Throw.
* src/real/format-output/cl_fmt_newroman.cc: Throw.
* src/real/format-output/cl_fmt_oldroman.cc: Throw.
* src/real/input/cl_R_read.cc: Throw.
* src/real/input/cl_R_read_stream.cc: Throw.
* src/real/misc/cl_R_as.cc: Throw.
* src/real/random/cl_R_random.cc: Throw.
* src/real/transcendental/cl_R_atan2.cc: Throw.
* src/real/transcendental/cl_R_log.cc: Throw.
* src/complex/input/cl_N_read.cc: Throw.
* src/complex/input/cl_N_read_stream.cc: Throw.
* src/complex/misc/cl_N_as.cc: Throw.
* src/complex/transcendental/cl_C_atanh_aux.cc: Throw.
* src/complex/transcendental/cl_C_expt_C.cc: Throw.
* src/complex/transcendental/cl_C_log.cc: Throw.
* src/complex/transcendental/cl_C_log2.cc: Throw.
* src/numtheory/cl_nt_cornacchia1.cc: Throw.
* src/numtheory/cl_nt_cornacchia4.cc: Throw.
* src/numtheory/cl_nt_isprobprime.cc: Throw.
* src/numtheory/cl_nt_jacobi.cc: Throw.
* src/numtheory/cl_nt_jacobi_low.cc: Throw.
* src/numtheory/cl_nt_sqrtmodp.cc: Throw.
* src/modinteger/cl_MI.cc: Throw.
* src/modinteger/cl_MI_int.h: Throw.
* src/modinteger/cl_MI_montgom.h: Throw.
* src/modinteger/cl_MI_pow2.h: Throw.
* src/modinteger/cl_MI_rshift.cc: Throw.
* src/modinteger/cl_MI_std.h: Throw.
* src/polynomial/elem/cl_UP_GF2.h: Throw.
* src/polynomial/elem/cl_UP_MI.h: Throw.
* src/polynomial/elem/cl_UP_gen.h: Throw.
* src/polynomial/elem/cl_UP_named.cc: Throw.
* src/polynomial/elem/cl_UP_no_ring.cc (uninitialized_error,
uninitialized_ring): Removed (see cln/ring.h.)
* src/polynomial/elem/cl_UP_number.h: Throw.
* src/polynomial/elem/cl_UP_unnamed.cc: Throw.
* src/vector/cl_GV_I.cc: Throw.
* src/vector/cl_GV_number.cc: Throw.
* tests/timediv2adic-compare.cc: Use default abort(), not cl_abort().
* tests/timeprint-compare.cc: Likewise.
* tests/timerecip2adic-compare.cc: Likewise.
* doc/cln.tex: Document the exception classes.
* examples/contfrac.cc: Use try/catch instead of setjmp/longjmp.
* INSTALL: undocument -fno-exceptions.
* README: Add exceptions to list of used C++ features.
18 years ago |
|
// 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_word_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(__LP64__)) || (defined(__sparc__) && !defined(__arch64__)) || defined(__hppa__) || defined(__arm__) || defined(__rs6000__) || defined(__m88k__) || defined(__convex__) || (defined(__s390__) && !defined(__s390x__)) || defined(__sh__) || (defined(__x86_64__) && defined(__ILP32__))
#define cl_word_alignment 4
#endif
#if defined(__alpha__) || defined(__ia64__) || defined(__mips64__) || defined(__powerpc64__) || (defined(__sparc__) && defined(__arch64__)) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(__s390x__) || defined(__aarch64__)
#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) : pointer (p) {} // 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) : pointer (p) {} // 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) : pointer (p) {} // 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) : pointer (p) {} // 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 */
|