]> www.ginac.de Git - cln.git/commitdiff
Replace CL_REQUIRE/CL_PROVIDE(cl_MI) with portable code.
authorAlexei Sheplyakov <varg@theor.jinr.ru>
Thu, 21 Aug 2008 11:56:43 +0000 (15:56 +0400)
committerAlexei Sheplyakov <varg@theor.jinr.ru>
Wed, 27 Aug 2008 04:41:05 +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/modinteger.h
src/modinteger/cl_MI.cc

index 877e7e9db640f6dfc64bb42ed6a55feb359bc391..7830286638e91c65fd867898c27d4b2a0c352570 100644 (file)
@@ -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.
 
index a3d55116e7aecc6f0dd7a0c1e32a7c8845100c29..3463d1f72466f9b35f8540d680d2523aff50bf58 100644 (file)
@@ -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)