]> www.ginac.de Git - cln.git/commitdiff
replace CL_REQUIRE/CL_PROVIDE(cl_0_ring) with (more) portable code.
authorAlexei Sheplyakov <varg@theor.jinr.ru>
Thu, 21 Aug 2008 09:05:39 +0000 (13:05 +0400)
committerAlexei Sheplyakov <varg@theor.jinr.ru>
Wed, 27 Aug 2008 04:41:02 +0000 (08:41 +0400)
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/null_ring.h
src/integer/ring/cl_0_ring.cc

index 474bdea7aa3152fb4eb7c8128b081804b5f46a2b..b26f66e3e0c5320e189664b55d30d5ccbef37b85 100644 (file)
@@ -9,7 +9,15 @@ namespace cln {
 
 class cl_null_ring : public cl_ring { public: cl_null_ring (); };
 extern const cl_null_ring cl_0_ring;           // math. {0}
-//CL_REQUIRE(cl_0_ring)
+
+class cl_0_ring_init_helper
+{
+       static int count;
+public:
+       cl_0_ring_init_helper();
+       ~cl_0_ring_init_helper();
+};
+static cl_0_ring_init_helper cl_0_ring_init_helper_instance;
 
 }  // namespace cln
 
index 722c03876da5e882c2d72749a83647cd460bb2d6..cc42acb38f36e7be5971041368a86974332c832e 100644 (file)
@@ -3,7 +3,6 @@
 // General includes.
 #include "cl_sysdep.h"
 
-CL_PROVIDE(cl_0_ring)
 
 // Specification.
 #include "cln/null_ring.h"
@@ -74,34 +73,48 @@ static const _cl_ring_element null_expt_pos (cl_heap_ring* R, const _cl_ring_ele
        return _cl_ring_element(R, (cl_I)0);
 }
 
-static cl_ring_setops null_setops = {
-       null_fprint,
-       null_equal
-};
-static cl_ring_addops null_addops = {
-       null_zero,
-       null_zerop,
-       null_plus,
-       null_minus,
-       null_uminus
-};
-static cl_ring_mulops null_mulops = {
-       null_one,
-       null_canonhom,
-       null_mul,
-       null_square,
-       null_expt_pos
-};
+static cl_ring_setops& null_setops()
+{
+       static cl_ring_setops ops = {
+               null_fprint,
+               null_equal
+       };
+       return ops;
+}
+
+static cl_ring_addops& null_addops()
+{
+       static cl_ring_addops ops = {
+               null_zero,
+               null_zerop,
+               null_plus,
+               null_minus,
+               null_uminus
+       };
+       return ops;
+}
+
+static cl_ring_mulops& null_mulops()
+{
+       static cl_ring_mulops ops = {
+                null_one,
+                null_canonhom,
+                null_mul,
+                null_square,
+                null_expt_pos
+       };
+       return ops;
+}
 
-extern cl_class cl_class_null_ring;
+static const cl_class& cl_class_null_ring();
 
 class cl_heap_null_ring : public cl_heap_ring {
        SUBCLASS_cl_heap_ring()
 public:
        // Constructor.
        cl_heap_null_ring ()
-               : cl_heap_ring (&null_setops,&null_addops,&null_mulops)
-               { type = &cl_class_null_ring; }
+               : cl_heap_ring (&null_setops(),&null_addops(),&null_mulops())
+               { type = &cl_class_null_ring(); }
        // Destructor.
        ~cl_heap_null_ring () {}
 };
@@ -117,17 +130,38 @@ static void cl_null_ring_dprint (cl_heap* pointer)
        fprint(cl_debugout, "(cl_null_ring) cl_0_ring");
 }
 
-cl_class cl_class_null_ring = {
-       cl_null_ring_destructor,
-       cl_class_flags_number_ring,
-       cl_null_ring_dprint
-};
+static const cl_class& cl_class_null_ring()
+{
+       static const cl_class cl_class_null_ring_instance = {
+                cl_null_ring_destructor,
+                cl_class_flags_number_ring,
+                cl_null_ring_dprint
+       };
+       return cl_class_null_ring_instance;
+}
+
+cl_heap_null_ring* cl_heap_null_ring_instance;
+const cl_null_ring cl_0_ring = cl_0_ring;
 
 inline cl_null_ring::cl_null_ring ()
-       : cl_ring (new cl_heap_null_ring()) {}
+       : cl_ring(cl_heap_null_ring_instance) {}
+
+int cl_0_ring_init_helper::count = 0;
 
-const cl_null_ring cl_0_ring;
+cl_0_ring_init_helper::cl_0_ring_init_helper()
+{
+       if (count++ == 0) {
+               cl_heap_null_ring_instance = new cl_heap_null_ring();
+               new ((void *)&cl_0_ring) cl_null_ring();
+        }
+}
+
+cl_0_ring_init_helper::~cl_0_ring_init_helper()
+{
+       if (--count == 0) {
+                delete cl_heap_null_ring_instance;
+       }
+}
 
 }  // namespace cln
 
-CL_PROVIDE_END(cl_0_ring)