made CGAL::Residue thread safe using

boost thread_specific_ptr from <boost/thread/tss.hpp>
This commit is contained in:
Michael Hemmer 2008-09-16 07:31:18 +00:00
parent 36ba068665
commit 909c7ed95c
2 changed files with 85 additions and 28 deletions

View File

@ -26,19 +26,26 @@
#include <cfloat>
#include <boost/operators.hpp>
#ifdef CGAL_HAS_THREADS
# include <boost/thread/tss.hpp>
#endif
CGAL_BEGIN_NAMESPACE
// fwd
void force_ieee_double_precision();
namespace CGALi{
#ifdef CGAL_HAS_THREADS
#else
namespace CGALi{
struct Modular_arithmetic_needs_ieee_double_precision{
Modular_arithmetic_needs_ieee_double_precision(){
CGAL::force_ieee_double_precision();
}
Modular_arithmetic_needs_ieee_double_precision(){
CGAL::force_ieee_double_precision();
}
};
}
} // namespace CGALi
#endif
class Residue;
@ -69,15 +76,51 @@ public:
private:
static const double CST_CUT;
static const CGALi::Modular_arithmetic_needs_ieee_double_precision
modular_arithmetic_needs_ieee_double_precision;
private:
static int prime_int;
static double prime;
static double prime_inv;
#ifdef CGAL_HAS_THREADS
static boost::thread_specific_ptr<int> prime_int_;
static boost::thread_specific_ptr<double> prime_;
static boost::thread_specific_ptr<double> prime_inv_;
static void init_class_for_thread(){
CGAL_precondition(prime_int_.get() == NULL);
CGAL_precondition(prime_.get() == NULL);
CGAL_precondition(prime_inv_.get() == NULL);
prime_int_.reset(new int(67111067));
prime_.reset(new double(67111067.0));
prime_inv_.reset(new double(1.0/67111067.0));
CGAL::force_ieee_double_precision();
}
static inline int get_prime_int(){
if (prime_int_.get() == NULL)
init_class_for_thread();
return *prime_int_.get();
}
static inline double get_prime(){
if (prime_.get() == NULL)
init_class_for_thread();
return *prime_.get();
}
static inline double get_prime_inv(){
if (prime_inv_.get() == NULL)
init_class_for_thread();
return *prime_inv_.get();
}
#else
static int prime_int;
static double prime;
static double prime_inv;
static int get_prime_int(){ return prime_int;}
static double get_prime() { return prime;}
static double get_prime_inv(){ return prime_inv;}
// calls force_ieee_double_precision(); within constructor
static const CGALi::Modular_arithmetic_needs_ieee_double_precision
modular_arithmetic_needs_ieee_double_precision;
#endif
/* Quick integer rounding, valid if a<2^51. for double */
static inline
double RES_round (double a){
@ -102,13 +145,14 @@ private:
/* Big modular reduction (e.g. after multiplication) */
static inline
double RES_reduce (double a){
return a - prime * RES_round(a * prime_inv);
return a - get_prime() * RES_round(a * get_prime_inv());
}
/* Little modular reduction (e.g. after a simple addition). */
static inline
double RES_soft_reduce (double a){
double prime = get_prime();
double b = 2*a;
return (b>prime) ? a-prime :
((b<-prime) ? a+prime : a);
@ -142,7 +186,7 @@ private:
double RES_inv (double ri1){
double bi = 0.0;
double bi1 = 1.0;
double ri = prime;
double ri = get_prime();
double p, tmp, tmp2;
Real_embeddable_traits<double>::Abs double_abs;
@ -175,16 +219,23 @@ public:
*
*/
static int
set_current_prime(int p){
int old_prime = prime_int;
prime_int = p;
prime = (double)p;
prime_inv = (double)1/prime;
return old_prime;
set_current_prime(int p){
int old_prime = get_prime_int();
#ifdef CGAL_HAS_THREADS
*prime_int_.get() = p;
*prime_.get() = double(p);
*prime_inv_.get() = 1.0/double(p);
#else
prime_int = p;
prime = double(p);
prime_inv = 1.0 / prime;
#endif
return old_prime;
}
/*! \brief return the current prime. */
/*! \brief return the current prime. */
static int get_current_prime(){
return prime_int;
return get_prime_int();
}
int get_value() const{
return int(x_);

View File

@ -21,13 +21,19 @@
#include <CGAL/Modular_arithmetic/Residue_type.h>
namespace CGAL{
#ifdef CGAL_HAS_THREADS
boost::thread_specific_ptr<int> Residue::prime_int_;
boost::thread_specific_ptr<double> Residue::prime_;
boost::thread_specific_ptr<double> Residue::prime_inv_;
#else
int Residue::prime_int = 67111067;
double Residue::prime =67111067.0;
double Residue::prime = 67111067.0;
double Residue::prime_inv =1/67111067.0;
const double Residue::CST_CUT = std::ldexp( 3., 51 );
const CGALi::Modular_arithmetic_needs_ieee_double_precision
Residue::modular_arithmetic_needs_ieee_double_precision
= CGALi::Modular_arithmetic_needs_ieee_double_precision();
#endif
const double Residue::CST_CUT = std::ldexp( 3., 51 );
}