fix potential threading problem with initialization of static objects

pull/2/head
weidai 2003-07-29 01:18:33 +00:00
parent 259ee22eba
commit 9c5c4769a9
15 changed files with 169 additions and 120 deletions

2
dh.h
View File

@ -78,7 +78,7 @@ public:
private:
const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
{static KeyAgreementAlgorithm a; return a;}
{return Singleton<KeyAgreementAlgorithm>().Ref();}
DL_GroupParameters<Element> & AccessAbstractGroupParameters()
{return m_groupParameters;}

View File

@ -171,8 +171,7 @@ bool EC2N::Equal(const Point &P, const Point &Q) const
const EC2N::Point& EC2N::Identity() const
{
static const Point zero;
return zero;
return Singleton<Point>().Ref();
}
const EC2N::Point& EC2N::Inverse(const Point &P) const

View File

@ -195,8 +195,7 @@ bool ECP::Equal(const Point &P, const Point &Q) const
const ECP::Point& ECP::Identity() const
{
static const Point zero;
return zero;
return Singleton<Point>().Ref();
}
const ECP::Point& ECP::Inverse(const Point &P) const

View File

@ -111,16 +111,23 @@ PolynomialMod2 PolynomialMod2::Pentanomial(unsigned t0, unsigned t1, unsigned t2
return r;
}
template <word i>
struct NewPolynomialMod2
{
PolynomialMod2 * operator()() const
{
return new PolynomialMod2(i);
}
};
const PolynomialMod2 &PolynomialMod2::Zero()
{
static const PolynomialMod2 zero;
return zero;
return Singleton<PolynomialMod2>().Ref();
}
const PolynomialMod2 &PolynomialMod2::One()
{
static const PolynomialMod2 one = 1;
return one;
return Singleton<PolynomialMod2, NewPolynomialMod2<1> >().Ref();
}
void PolynomialMod2::Decode(const byte *input, unsigned int inputLen)

View File

@ -40,7 +40,7 @@ word64 Timer::GetCurrentTimerValue()
word64 Timer::TicksPerSecond()
{
#if defined(CRYPTOPP_WIN32_AVAILABLE)
static LARGE_INTEGER freq;
static LARGE_INTEGER freq = {0};
if (freq.QuadPart == 0)
{
if (!QueryPerformanceFrequency(&freq))

View File

@ -2834,22 +2834,28 @@ Integer Integer::Power2(unsigned int e)
return r;
}
template <long i>
struct NewInteger
{
Integer * operator()() const
{
return new Integer(i);
}
};
const Integer &Integer::Zero()
{
static const Integer zero;
return zero;
return Singleton<Integer>().Ref();
}
const Integer &Integer::One()
{
static const Integer one(1,2);
return one;
return Singleton<Integer, NewInteger<1> >().Ref();
}
const Integer &Integer::Two()
{
static const Integer two(2,2);
return two;
return Singleton<Integer, NewInteger<2> >().Ref();
}
bool Integer::operator!() const

42
misc.h
View File

@ -209,29 +209,57 @@ inline CipherDir GetCipherDir(const T &obj)
return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
}
template <class T>
struct NewObject
{
T* operator()() const {return new T;}
};
// This function safely initializes a static object in a multithreaded environment without using locks.
// It may leak memory when two threads try to initialize the static object at the same time
// but this should be acceptable since each static object is only initialized once per session.
template <class T, class F>
T & StaticObject(F NewT, T *dummy=NULL)
template <class T, class F = NewObject<T>, int instance=0>
class Singleton
{
static member_ptr<T> s_pObject;
public:
Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
// VC60 workaround: use "..." to prevent this function from being inlined
const T & Ref(...) const;
private:
F m_objectFactory;
};
template <class T, class F, int instance>
const T & Singleton<T, F, instance>::Ref(...) const
{
static simple_ptr<T> s_pObject;
static char s_objectState = 0;
retry:
switch (s_objectState)
{
case 0:
s_objectState = 1;
s_pObject.reset(NewT());
try
{
s_pObject.m_p = m_objectFactory();
}
catch(...)
{
s_objectState = 0;
throw;
}
s_objectState = 2;
break;
case 1:
while (s_objectState == 1) {}
goto retry;
default:
break;
}
return *s_pObject;
};
return *s_pObject.m_p;
}
// ************** rotate functions ***************

View File

@ -15,7 +15,9 @@ NAMESPACE_BEGIN(CryptoPP)
const word s_lastSmallPrime = 32719;
std::vector<word16> * NewPrimeTable()
struct NewPrimeTable
{
std::vector<word16> * operator()() const
{
const unsigned int maxPrimeTableSize = 3511;
@ -41,10 +43,11 @@ std::vector<word16> * NewPrimeTable()
return pPrimeTable.release();
}
};
const word16 * GetPrimeTable(unsigned int &size)
{
std::vector<word16> &primeTable = StaticObject<std::vector<word16> >(&NewPrimeTable);
const std::vector<word16> &primeTable = Singleton<std::vector<word16>, NewPrimeTable>().Ref();
size = primeTable.size();
return &primeTable[0];
}
@ -218,13 +221,19 @@ bool IsStrongLucasProbablePrime(const Integer &n)
return false;
}
struct NewLastSmallPrimeSquared
{
Integer * operator()() const
{
return new Integer(Integer(s_lastSmallPrime).Squared());
}
};
bool IsPrime(const Integer &p)
{
static const Integer lastSmallPrimeSquared = Integer(s_lastSmallPrime).Squared();
if (p <= s_lastSmallPrime)
return IsSmallPrime(p);
else if (p <= lastSmallPrimeSquared)
else if (p <= Singleton<Integer, NewLastSmallPrimeSquared>().Ref())
return SmallDivisorsTest(p);
else
return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p);

View File

@ -565,15 +565,13 @@ Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const E
template <class T, int instance>
const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::Zero()
{
static const PolynomialOverFixedRing<T, instance> zero;
return zero;
return Singleton<ThisType>().Ref();
}
template <class T, int instance>
const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::One()
{
static const PolynomialOverFixedRing<T, instance> one = fixedRing.MultiplicativeIdentity();
return one;
return Singleton<ThisType, NewOnePolynomial>().Ref();
}
NAMESPACE_END

View File

@ -170,7 +170,7 @@ public:
//! \name CREATORS
//@{
//! creates the zero polynomial
PolynomialOverFixedRing(unsigned int count = 0) : B(fixedRing, count) {}
PolynomialOverFixedRing(unsigned int count = 0) : B(ms_fixedRing, count) {}
//! copy constructor
PolynomialOverFixedRing(const ThisType &t) : B(t) {}
@ -185,7 +185,7 @@ public:
: B(first, last) {}
//! convert from string
explicit PolynomialOverFixedRing(const char *str) : B(str, fixedRing) {}
explicit PolynomialOverFixedRing(const char *str) : B(str, ms_fixedRing) {}
//! convert from big-endian byte array
PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {}
@ -197,7 +197,7 @@ public:
explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {}
//! create a random PolynomialOverFixedRing
PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter &parameter) : B(rng, parameter, fixedRing) {}
PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter &parameter) : B(rng, parameter, ms_fixedRing) {}
static const ThisType &Zero();
static const ThisType &One();
@ -206,13 +206,13 @@ public:
//! \name ACCESSORS
//@{
//! the zero polynomial will return a degree of -1
int Degree() const {return B::Degree(fixedRing);}
int Degree() const {return B::Degree(ms_fixedRing);}
//! degree + 1
unsigned int CoefficientCount() const {return B::CoefficientCount(fixedRing);}
unsigned int CoefficientCount() const {return B::CoefficientCount(ms_fixedRing);}
//! return coefficient for x^i
CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, fixedRing);}
CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
//! return coefficient for x^i
CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, fixedRing);}
CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
//@}
//! \name MANIPULATORS
@ -220,9 +220,9 @@ public:
//!
ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;}
//!
ThisType& operator+=(const ThisType& t) {Accumulate(t, fixedRing); return *this;}
ThisType& operator+=(const ThisType& t) {Accumulate(t, ms_fixedRing); return *this;}
//!
ThisType& operator-=(const ThisType& t) {Reduce(t, fixedRing); return *this;}
ThisType& operator-=(const ThisType& t) {Reduce(t, ms_fixedRing); return *this;}
//!
ThisType& operator*=(const ThisType& t) {return *this = *this*t;}
//!
@ -231,18 +231,18 @@ public:
ThisType& operator%=(const ThisType& t) {return *this = *this%t;}
//!
ThisType& operator<<=(unsigned int n) {ShiftLeft(n, fixedRing); return *this;}
ThisType& operator<<=(unsigned int n) {ShiftLeft(n, ms_fixedRing); return *this;}
//!
ThisType& operator>>=(unsigned int n) {ShiftRight(n, fixedRing); return *this;}
ThisType& operator>>=(unsigned int n) {ShiftRight(n, ms_fixedRing); return *this;}
//! set the coefficient for x^i to value
void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, fixedRing);}
void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, ms_fixedRing);}
//!
void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter) {B::Randomize(rng, parameter, fixedRing);}
void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter) {B::Randomize(rng, parameter, ms_fixedRing);}
//!
void Negate() {B::Negate(fixedRing);}
void Negate() {B::Negate(ms_fixedRing);}
void swap(ThisType &t) {B::swap(t);}
//@}
@ -254,7 +254,7 @@ public:
//!
ThisType operator+() const {return *this;}
//!
ThisType operator-() const {return ThisType(Inverse(fixedRing));}
ThisType operator-() const {return ThisType(Inverse(ms_fixedRing));}
//@}
//! \name BINARY OPERATORS
@ -268,34 +268,42 @@ public:
//! \name OTHER ARITHMETIC FUNCTIONS
//@{
//!
ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(fixedRing));}
ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(ms_fixedRing));}
//!
bool IsUnit() const {return B::IsUnit(fixedRing);}
bool IsUnit() const {return B::IsUnit(ms_fixedRing);}
//!
ThisType Doubled() const {return ThisType(B::Doubled(fixedRing));}
ThisType Doubled() const {return ThisType(B::Doubled(ms_fixedRing));}
//!
ThisType Squared() const {return ThisType(B::Squared(fixedRing));}
ThisType Squared() const {return ThisType(B::Squared(ms_fixedRing));}
CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, fixedRing);}
CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, ms_fixedRing);}
//! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d)
{B::Divide(r, q, a, d, fixedRing);}
{B::Divide(r, q, a, d, ms_fixedRing);}
//@}
//! \name INPUT/OUTPUT
//@{
//!
friend std::istream& operator>>(std::istream& in, ThisType &a)
{return a.Input(in, fixedRing);}
{return a.Input(in, ms_fixedRing);}
//!
friend std::ostream& operator<<(std::ostream& out, const ThisType &a)
{return a.Output(out, fixedRing);}
{return a.Output(out, ms_fixedRing);}
//@}
private:
static const Ring fixedRing;
struct NewOnePolynomial
{
ThisType * operator()() const
{
return new ThisType(ms_fixedRing.MultiplicativeIdentity());
}
};
static const Ring ms_fixedRing;
};
//! Ring of polynomials over another ring
@ -391,7 +399,7 @@ Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const E
//!
template <class T, int instance>
inline bool operator==(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return a.Equals(b, fixedRing);}
{return a.Equals(b, ms_fixedRing);}
//!
template <class T, int instance>
inline bool operator!=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
@ -417,23 +425,23 @@ inline bool operator<=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a,
//!
template <class T, int instance>
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator+(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Plus(b, fixedRing));}
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Plus(b, ms_fixedRing));}
//!
template <class T, int instance>
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator-(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Minus(b, fixedRing));}
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Minus(b, ms_fixedRing));}
//!
template <class T, int instance>
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator*(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Times(b, fixedRing));}
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Times(b, ms_fixedRing));}
//!
template <class T, int instance>
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator/(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.DividedBy(b, fixedRing));}
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.DividedBy(b, ms_fixedRing));}
//!
template <class T, int instance>
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator%(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Modulo(b, fixedRing));}
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Modulo(b, ms_fixedRing));}
NAMESPACE_END

View File

@ -414,7 +414,7 @@ public:
protected:
const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
{static typename SCHEME_OPTIONS::MessageEncodingMethod messageEncodingMethod; return messageEncodingMethod;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
{return GetKey();}
const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
@ -1322,17 +1322,17 @@ public:
protected:
const DL_ElgamalLikeSignatureAlgorithm<Element> & GetSignatureAlgorithm() const
{static typename SCHEME_OPTIONS::SignatureAlgorithm a; return a;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SignatureAlgorithm>().Ref();}
const DL_KeyAgreementAlgorithm<Element> & GetKeyAgreementAlgorithm() const
{static typename SCHEME_OPTIONS::KeyAgreementAlgorithm a; return a;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyAgreementAlgorithm>().Ref();}
const DL_KeyDerivationAlgorithm<Element> & GetKeyDerivationAlgorithm() const
{static typename SCHEME_OPTIONS::KeyDerivationAlgorithm a; return a;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::KeyDerivationAlgorithm>().Ref();}
const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const
{static typename SCHEME_OPTIONS::SymmetricEncryptionAlgorithm a; return a;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::SymmetricEncryptionAlgorithm>().Ref();}
HashIdentifier GetHashIdentifier() const
{return HashIdentifier();}
const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const
{static typename SCHEME_OPTIONS::MessageEncodingMethod a; return a;}
{return Singleton<CPP_TYPENAME SCHEME_OPTIONS::MessageEncodingMethod>().Ref();}
};
//! .

View File

@ -8,10 +8,9 @@
NAMESPACE_BEGIN(CryptoPP)
GFP2Element & GFP2Element::Zero()
const GFP2Element & GFP2Element::Zero()
{
static GFP2Element zero;
return zero;
return Singleton<GFP2Element>().Ref();
}
void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer &q, GFP2Element &g, unsigned int pbits, unsigned int qbits)

2
xtr.h
View File

@ -33,7 +33,7 @@ public:
c2.swap(a.c2);
}
static GFP2Element & Zero();
static const GFP2Element & Zero();
Integer c1, c2;
};

View File

@ -483,15 +483,15 @@ bool Inflator::DecodeBody()
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
const HuffmanDecoder* pLiteralDecoder = GetLiteralDecoder();
const HuffmanDecoder* pDistanceDecoder = GetDistanceDecoder();
const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();
switch (m_nextDecode)
{
case LITERAL:
while (true)
{
if (!pLiteralDecoder->Decode(m_reader, m_literal))
if (!literalDecoder.Decode(m_reader, m_literal))
{
m_nextDecode = LITERAL;
break;
@ -517,7 +517,7 @@ bool Inflator::DecodeBody()
}
m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
case DISTANCE:
if (!pDistanceDecoder->Decode(m_reader, m_distance))
if (!distanceDecoder.Decode(m_reader, m_distance))
{
m_nextDecode = DISTANCE;
break;
@ -567,45 +567,41 @@ void Inflator::FlushOutput()
}
}
const HuffmanDecoder *Inflator::FixedLiteralDecoder()
struct NewFixedLiteralDecoder
{
static simple_ptr<HuffmanDecoder> s_pDecoder;
if (!s_pDecoder.m_p)
HuffmanDecoder * operator()() const
{
unsigned int codeLengths[288];
std::fill(codeLengths + 0, codeLengths + 144, 8);
std::fill(codeLengths + 144, codeLengths + 256, 9);
std::fill(codeLengths + 256, codeLengths + 280, 7);
std::fill(codeLengths + 280, codeLengths + 288, 8);
HuffmanDecoder *pDecoder = new HuffmanDecoder;
std::auto_ptr<HuffmanDecoder> pDecoder(new HuffmanDecoder);
pDecoder->Initialize(codeLengths, 288);
s_pDecoder.m_p = pDecoder;
}
return s_pDecoder.m_p;
return pDecoder.release();
}
};
const HuffmanDecoder *Inflator::FixedDistanceDecoder()
struct NewFixedDistanceDecoder
{
static simple_ptr<HuffmanDecoder> s_pDecoder;
if (!s_pDecoder.m_p)
HuffmanDecoder * operator()() const
{
unsigned int codeLengths[32];
std::fill(codeLengths + 0, codeLengths + 32, 5);
HuffmanDecoder *pDecoder = new HuffmanDecoder;
std::auto_ptr<HuffmanDecoder> pDecoder(new HuffmanDecoder);
pDecoder->Initialize(codeLengths, 32);
s_pDecoder.m_p = pDecoder;
return pDecoder.release();
}
return s_pDecoder.m_p;
};
const HuffmanDecoder& Inflator::GetLiteralDecoder() const
{
return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedLiteralDecoder>().Ref() : m_dynamicLiteralDecoder;
}
const HuffmanDecoder *Inflator::GetLiteralDecoder() const
const HuffmanDecoder& Inflator::GetDistanceDecoder() const
{
return m_blockType == 1 ? FixedLiteralDecoder() : &m_dynamicLiteralDecoder;
}
const HuffmanDecoder *Inflator::GetDistanceDecoder() const
{
return m_blockType == 1 ? FixedDistanceDecoder() : &m_dynamicDistanceDecoder;
return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedDistanceDecoder>().Ref() : m_dynamicDistanceDecoder;
}
NAMESPACE_END

View File

@ -127,8 +127,8 @@ private:
static const HuffmanDecoder *FixedLiteralDecoder();
static const HuffmanDecoder *FixedDistanceDecoder();
const HuffmanDecoder *GetLiteralDecoder() const;
const HuffmanDecoder *GetDistanceDecoder() const;
const HuffmanDecoder& GetLiteralDecoder() const;
const HuffmanDecoder& GetDistanceDecoder() const;
enum State {PRE_STREAM, WAIT_HEADER, DECODING_BODY, POST_STREAM, AFTER_END};
State m_state;