Browse Source

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.
master
Alexei Sheplyakov 16 years ago
parent
commit
2ee2f08875
  1. 14
      include/cln/modinteger.h
  2. 65
      src/modinteger/cl_MI.cc

14
include/cln/modinteger.h

@ -46,7 +46,16 @@ extern const cl_modint_ring cl_modint0_ring;
// Default constructor. This avoids dealing with NULL pointers. // Default constructor. This avoids dealing with NULL pointers.
inline cl_modint_ring::cl_modint_ring () inline cl_modint_ring::cl_modint_ring ()
: cl_ring (as_cl_private_thing(cl_modint0_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. // Copy constructor and assignment operator.
CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring) CL_DEFINE_COPY_CONSTRUCTOR2(cl_modint_ring,cl_ring)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_modint_ring,cl_modint_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 // Lookup or create a modular integer ring Z/mZ
extern const cl_modint_ring find_modint_ring (const cl_I& m); 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. // Operations on modular integers.

65
src/modinteger/cl_MI.cc

@ -3,12 +3,9 @@
// General includes. // General includes.
#include "cl_sysdep.h" #include "cl_sysdep.h"
CL_PROVIDE(cl_MI)
// Specification. // Specification.
#include "cln/modinteger.h" #include "cln/modinteger.h"
// Implementation. // Implementation.
#include "cl_I.h" #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_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) 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) : 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; return false;
} }
static const cl_wht_from_integer_to_rcpointer modint_ring_table = cl_wht_from_integer_to_rcpointer(maygc_htentry);
static inline cl_modint_ring* get_modint_ring (const cl_I& m)
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);
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 void store_modint_ring (const cl_modint_ring& R)
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()
{ {
modint_ring_table.put(R->modulus,R);
if (count++ == 0)
modint_ring_table = new cl_wht_from_integer_to_rcpointer(maygc_htentry);
} }
modint_ring_cache::~modint_ring_cache()
{
if (--count == 0)
delete modint_ring_table;
}
const cl_modint_ring find_modint_ring (const cl_I& m) const cl_modint_ring find_modint_ring (const cl_I& m)
{ {
{ Mutable(cl_I,m); { Mutable(cl_I,m);
m = abs(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) { if (!ring_in_table) {
var cl_modint_ring R = make_modint_ring(m); 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) if (!ring_in_table)
throw runtime_exception(); throw runtime_exception();
} }
return *ring_in_table; 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 } // namespace cln
CL_PROVIDE_END(cl_MI)
Loading…
Cancel
Save