From effb39946984178088feafba29a007f32009c23f Mon Sep 17 00:00:00 2001 From: Alexei Sheplyakov Date: Thu, 21 Aug 2008 21:18:57 +0400 Subject: [PATCH] Replace CL_REQUIRE/CL_PROVIDE(cl_GV_number) with portable code. The order of initialization of non-local objects in different compilation units is not specified in C++. Hence special care should be taken to avoid static initialization order fiasco. CLN solved the problem with some evil (GCC specific, and even GCC-version-specific) hack. Replace it with a technique similar to one used in STL to initialize std::cout and friends. --- include/cln/GV_number.h | 9 +++++- src/vector/cl_GV_number.cc | 50 ++++++++++++++++++++++---------- src/vector/cl_GV_number_debug.cc | 2 +- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/include/cln/GV_number.h b/include/cln/GV_number.h index 29886ca..10edc88 100644 --- a/include/cln/GV_number.h +++ b/include/cln/GV_number.h @@ -32,7 +32,14 @@ inline cl_GV_number::cl_GV_number (uintC len) extern const cl_GV_number cl_null_GV_number; inline cl_GV_number::cl_GV_number () : cl_GV ((cl_heap_GV_number*) cl_null_GV_number) {} -CL_REQUIRE(cl_GV_number) +class cl_GV_number_init_helper +{ + static int count; +public: + cl_GV_number_init_helper(); + ~cl_GV_number_init_helper(); +}; +static cl_GV_number_init_helper cl_GV_number_init_helper_instance; // Copy a vector. extern const cl_GV_number copy (const cl_GV_number&); diff --git a/src/vector/cl_GV_number.cc b/src/vector/cl_GV_number.cc index 7a65eb9..6c47891 100644 --- a/src/vector/cl_GV_number.cc +++ b/src/vector/cl_GV_number.cc @@ -3,8 +3,6 @@ // General includes. #include "cl_sysdep.h" -CL_PROVIDE(cl_GV_number) - // Specification. #include "cln/GV_number.h" @@ -25,11 +23,16 @@ static void cl_gvector_number_destructor (cl_heap* pointer) #endif } -cl_class cl_class_gvector_number = { - cl_gvector_number_destructor, - 0 -}; - +// XXX: this ought to be const, but it would be impossible to register +// the printing function (in cl_GV_number_debug.cc) +cl_class& cl_class_gvector_number() +{ + static cl_class instance = { + cl_gvector_number_destructor, + 0 + }; + return instance; +} static inline cl_heap_GV_number * outcast (cl_GV_inner* vec) { @@ -90,18 +93,19 @@ static void general_copy_elements (const cl_GV_inner* srcvec, uintC s } } -static cl_GV_vectorops general_vectorops = { - general_element, - general_set_element, - general_do_delete, - general_copy_elements -}; cl_heap_GV_number* cl_make_heap_GV_number (uintC len) { + static cl_GV_vectorops general_vectorops = { + general_element, + general_set_element, + general_do_delete, + general_copy_elements + }; + var cl_heap_GV_number_general* hv = (cl_heap_GV_number_general*) malloc_hook(offsetofa(cl_heap_GV_number_general,data)+sizeof(cl_number)*len); hv->refcount = 1; - hv->type = &cl_class_gvector_number; + hv->type = &cl_class_gvector_number(); new (&hv->v) cl_GV_inner (len,&general_vectorops); for (var uintC i = 0; i < len; i++) init1(cl_number, hv->data[i]) (); @@ -109,8 +113,22 @@ cl_heap_GV_number* cl_make_heap_GV_number (uintC len) } // An empty vector. -const cl_GV_number cl_null_GV_number = cl_GV_number((uintC)0); +const cl_GV_number cl_null_GV_number = cl_null_GV_number; + +int cl_GV_number_init_helper::count = 0; + +cl_GV_number_init_helper::cl_GV_number_init_helper() +{ + if (count++ == 0) + new ((void *)&cl_null_GV_number) cl_GV_number((uintC)0); +} + +cl_GV_number_init_helper::~cl_GV_number_init_helper() +{ + if (--count == 0) { + // Nothing to clean up + } +} } // namespace cln -CL_PROVIDE_END(cl_GV_number) diff --git a/src/vector/cl_GV_number_debug.cc b/src/vector/cl_GV_number_debug.cc index ad20f39..3c24bb7 100644 --- a/src/vector/cl_GV_number_debug.cc +++ b/src/vector/cl_GV_number_debug.cc @@ -29,7 +29,7 @@ static void dprint (cl_heap* pointer) print_vector(cl_debugout,default_print_flags,&print_for_debug,obj); } AT_INITIALIZATION(dprint_GV_number) -{ cl_register_type_printer(cl_class_gvector_number,dprint); } +{ extern cl_class& cl_class_gvector_number(); cl_class_gvector_number().dprint = dprint; } // This dummy links in this module when requires it. int cl_GV_number_debug_module;