From: Alexei Sheplyakov Date: Thu, 21 Aug 2008 11:56:43 +0000 (+0400) Subject: Replace CL_REQUIRE/CL_PROVIDE(cl_MI) with portable code. X-Git-Tag: cln_1-3-0~63 X-Git-Url: https://www.ginac.de/CLN/cln.git//cln.git?a=commitdiff_plain;h=2ee2f088755c856d4eed429ed7fcdf4ca519ae00;p=cln.git Replace CL_REQUIRE/CL_PROVIDE(cl_MI) 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. --- diff --git a/include/cln/modinteger.h b/include/cln/modinteger.h index 877e7e9..7830286 100644 --- a/include/cln/modinteger.h +++ b/include/cln/modinteger.h @@ -46,7 +46,16 @@ extern const cl_modint_ring cl_modint0_ring; // Default constructor. This avoids dealing with NULL pointers. inline cl_modint_ring::cl_modint_ring () : cl_ring (as_cl_private_thing(cl_modint0_ring)) {} -CL_REQUIRE(cl_MI) + +class cl_MI_init_helper +{ + static int count; +public: + cl_MI_init_helper(); + ~cl_MI_init_helper(); +}; +static cl_MI_init_helper cl_MI_init_helper_instance; + // Copy constructor and assignment operator. CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring) CL_DEFINE_ASSIGNMENT_OPERATOR(cl_modint_ring,cl_modint_ring) @@ -358,8 +367,7 @@ public: // Lookup or create a modular integer ring Z/mZ extern const cl_modint_ring find_modint_ring (const cl_I& m); -CL_REQUIRE(cl_MI) - +static cl_MI_init_helper cl_MI_init_helper_instance2; // Operations on modular integers. diff --git a/src/modinteger/cl_MI.cc b/src/modinteger/cl_MI.cc index a3d5511..3463d1f 100644 --- a/src/modinteger/cl_MI.cc +++ b/src/modinteger/cl_MI.cc @@ -3,12 +3,9 @@ // General includes. #include "cl_sysdep.h" -CL_PROVIDE(cl_MI) - // Specification. #include "cln/modinteger.h" - // Implementation. #include "cl_I.h" @@ -32,10 +29,7 @@ static void cl_modint_ring_destructor (cl_heap* pointer) (*(cl_heap_modint_ring*)pointer).~cl_heap_modint_ring(); } -cl_class cl_class_modint_ring = { - cl_modint_ring_destructor, - cl_class_flags_modint_ring -}; +cl_class cl_class_modint_ring; cl_heap_modint_ring::cl_heap_modint_ring (cl_I m, cl_modint_setops* setopv, cl_modint_addops* addopv, cl_modint_mulops* mulopv) : setops (setopv), addops (addopv), mulops (mulopv), modulus (m) @@ -149,37 +143,72 @@ static bool maygc_htentry (const cl_htentry_from_integer_to_rcpointer& entry) return false; } -static const cl_wht_from_integer_to_rcpointer modint_ring_table = cl_wht_from_integer_to_rcpointer(maygc_htentry); +class modint_ring_cache +{ + static cl_wht_from_integer_to_rcpointer* modint_ring_table; + static int count; +public: + inline cl_modint_ring* get_modint_ring(const cl_I& m) + { + return (cl_modint_ring*) modint_ring_table->get(m); + } + inline void store_modint_ring(const cl_modint_ring& R) + { + modint_ring_table->put(R->modulus,R); + } + modint_ring_cache(); + ~modint_ring_cache(); +}; -static inline cl_modint_ring* get_modint_ring (const cl_I& m) +cl_wht_from_integer_to_rcpointer* modint_ring_cache::modint_ring_table = 0; +int modint_ring_cache::count = 0; +modint_ring_cache::modint_ring_cache() { - return (cl_modint_ring*) modint_ring_table.get(m); + if (count++ == 0) + modint_ring_table = new cl_wht_from_integer_to_rcpointer(maygc_htentry); } -static inline void store_modint_ring (const cl_modint_ring& R) +modint_ring_cache::~modint_ring_cache() { - modint_ring_table.put(R->modulus,R); + if (--count == 0) + delete modint_ring_table; } - const cl_modint_ring find_modint_ring (const cl_I& m) { { Mutable(cl_I,m); m = abs(m); - var cl_modint_ring* ring_in_table = get_modint_ring(m); + static modint_ring_cache cache; + var cl_modint_ring* ring_in_table = cache.get_modint_ring(m); if (!ring_in_table) { var cl_modint_ring R = make_modint_ring(m); - store_modint_ring(R); - ring_in_table = get_modint_ring(m); + cache.store_modint_ring(R); + ring_in_table = cache.get_modint_ring(m); if (!ring_in_table) throw runtime_exception(); } return *ring_in_table; }} +const cl_modint_ring cl_modint0_ring = cl_modint0_ring; + +int cl_MI_init_helper::count = 0; -const cl_modint_ring cl_modint0_ring = find_modint_ring(0); +cl_MI_init_helper::cl_MI_init_helper() +{ + if (count++ == 0) { + cl_class_modint_ring.destruct = cl_modint_ring_destructor; + cl_class_modint_ring.flags = cl_class_flags_modint_ring; + new ((void *)&cl_modint0_ring) cl_modint_ring(find_modint_ring(0)); + } +} + +cl_MI_init_helper::~cl_MI_init_helper() +{ + if (--count == 0) { + // Nothing to clean up? + } +} } // namespace cln -CL_PROVIDE_END(cl_MI)