From da9fbcea6c2458ecac3c295ee56f1d002ffc2b17 Mon Sep 17 00:00:00 2001 From: Alexei Sheplyakov Date: Thu, 21 Aug 2008 15:18:34 +0400 Subject: [PATCH] Replace CL_REQUIRE/CL_PROVIDE(cl_C_ring) 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/complex_ring.h | 10 +++++++++- include/cln/univpoly_complex.h | 2 -- src/complex/ring/cl_C_ring.cc | 33 +++++++++++++++++++++++---------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/cln/complex_ring.h b/include/cln/complex_ring.h index ea7ca98..881867c 100644 --- a/include/cln/complex_ring.h +++ b/include/cln/complex_ring.h @@ -11,7 +11,15 @@ namespace cln { typedef cl_specialized_number_ring cl_complex_ring; extern const cl_complex_ring cl_C_ring; // math. C extern cl_class cl_class_complex_ring; -//CL_REQUIRE(cl_C_ring) + +class cl_C_ring_init_helper +{ + static int count; +public: + cl_C_ring_init_helper(); + ~cl_C_ring_init_helper(); +}; +static cl_C_ring_init_helper cl_C_ring_init_helper_instance; } // namespace cln diff --git a/include/cln/univpoly_complex.h b/include/cln/univpoly_complex.h index 3970d9d..eb2991a 100644 --- a/include/cln/univpoly_complex.h +++ b/include/cln/univpoly_complex.h @@ -223,8 +223,6 @@ inline const cl_UP_N deriv (const cl_UP_N& x) #endif -CL_REQUIRE(cl_C_ring) - } // namespace cln #endif /* _CL_UNIVPOLY_COMPLEX_H */ diff --git a/src/complex/ring/cl_C_ring.cc b/src/complex/ring/cl_C_ring.cc index 296971a..32d6ccf 100644 --- a/src/complex/ring/cl_C_ring.cc +++ b/src/complex/ring/cl_C_ring.cc @@ -3,8 +3,6 @@ // General includes. #include "cl_sysdep.h" -CL_PROVIDE(cl_C_ring) - // Specification. #include "cln/complex_ring.h" @@ -144,19 +142,34 @@ static void cl_complex_ring_dprint (cl_heap* pointer) fprint(cl_debugout, "(cl_complex_ring) cl_C_ring"); } -cl_class cl_class_complex_ring = { - cl_complex_ring_destructor, - cl_class_flags_number_ring, - cl_complex_ring_dprint -}; +cl_class cl_class_complex_ring; +static cl_heap_complex_ring* cl_heap_complex_ring_instance; +const cl_complex_ring cl_C_ring = cl_C_ring; // Constructor. template <> inline cl_complex_ring::cl_specialized_number_ring () - : cl_number_ring (new cl_heap_complex_ring()) {} + : cl_number_ring(cl_heap_complex_ring_instance) { } + +int cl_C_ring_init_helper::count = 0; + +cl_C_ring_init_helper::cl_C_ring_init_helper() +{ + if (count++ == 0) { + cl_class_complex_ring.destruct = cl_complex_ring_destructor; + cl_class_complex_ring.flags = cl_class_flags_number_ring; + cl_class_complex_ring.dprint = cl_complex_ring_dprint; + cl_heap_complex_ring_instance = new cl_heap_complex_ring(); + new ((void *)&cl_C_ring) cl_complex_ring(); + } +} -const cl_complex_ring cl_C_ring; +cl_C_ring_init_helper::~cl_C_ring_init_helper() +{ + if (--count == 0) { + delete cl_heap_complex_ring_instance; + } +} } // namespace cln -CL_PROVIDE_END(cl_C_ring)