From 00e39d3608fea0a37c505443fd34e8ff4833c150 Mon Sep 17 00:00:00 2001 From: Christian Kaiser Date: Thu, 7 May 2009 11:37:10 +0000 Subject: [PATCH] added thread-safety to static history buffers (factorial and logarithm) for MSVC git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@135 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmath.h | 2 ++ ttmath/ttmathbig.h | 25 ++++++++++++---- ttmath/ttmathconfig.h | 65 +++++++++++++++++++++++++++++++++++++++++- ttmath/ttmathobjects.h | 1 + 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index bec013a..e24e2d7 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -1951,6 +1951,8 @@ namespace ttmath } ErrorCode err_tmp; + + TTMATH_USE_THREADSAFE_OBJ(history); if( history.Get(x, result, err_tmp) ) { diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 7b619e8..4a7fff2 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -2506,7 +2506,19 @@ public: { operator=(value); } - + + class LogHistory + { + public: + Big val[15]; + + LogHistory() + { + for (int i = 0; i < 15; ++i) + val[i].SetZero(); + } + TTMATH_IMPLEMENT_THREADSAFE_OBJ + }; /*! a method for converting the value into a string with a base equal 'base' @@ -2793,11 +2805,12 @@ private: // (LnSurrounding1() will return one immediately) uint c = Ln(x); - // warning! this 'static' is not thread safe - static Big log_history[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint index = base - 2; - if( log_history[index].IsZero() ) + static LogHistory log_history; + TTMATH_USE_THREADSAFE_OBJ(log_history); + + if( log_history.val[index].IsZero() ) { // we don't have 'base' in 'log_history' then we calculate it now @@ -2815,14 +2828,14 @@ private: // the next time we'll get the 'Ln(base)' from the history, // this 'log_history' can have (16-2+1) items max - log_history[index] = temp; + log_history.val[index] = temp; c += Div(temp); } else { // we've calculated the 'Ln(base)' beforehand and we're getting it now - c += Div( log_history[index] ); + c += Div( log_history.val[index] ); } return (c==0)? 0 : 1; diff --git a/ttmath/ttmathconfig.h b/ttmath/ttmathconfig.h index 9b51dfa..ec9a341 100644 --- a/ttmath/ttmathconfig.h +++ b/ttmath/ttmathconfig.h @@ -57,7 +57,65 @@ namespace ttmath #define __TEXT(quote) quote #endif #define TTMATH_TEXT(quote) __TEXT(quote) -#else + + #if defined(_MT) + class clsCrit + { + private: + mutable CRITICAL_SECTION _Crit; + + clsCrit(const clsCrit&) // inhibit copy (easy mistake to do; use clsCritObj instead!!!) + { + } + clsCrit& operator=(const clsCrit& rhs); // inhibit assignment + public: + clsCrit(void) + { + ::InitializeCriticalSection(&_Crit); + } + virtual ~clsCrit(void) + { + ::DeleteCriticalSection(&_Crit); + } + + void Enter(void) const + { + ::EnterCriticalSection(&_Crit); + } + void Leave(void) const + { + ::LeaveCriticalSection(&_Crit); + } + }; + + class clsCritObj + { + private: + const clsCrit& _Crit; + + clsCritObj& operator=(const clsCritObj& rhs); // not applicable + public: + clsCritObj(const clsCrit& Sync) + : _Crit(Sync) + { + _Crit.Enter(); + } + ~clsCritObj(void) + { + _Crit.Leave(); + } + }; + #define TTMATH_IMPLEMENT_THREADSAFE_OBJ \ + private: \ + clsCrit CritSect; \ + public: \ + operator clsCrit&() \ + { \ + return(CritSect); \ + } + #define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c) + #endif +#else // not MS compiler typedef char tchar_t; typedef std::string tstr_t; typedef std::ostringstream tostrstrm_t; @@ -65,6 +123,11 @@ namespace ttmath typedef std::istream tistrm_t; #endif +#if !defined(TTMATH_IMPLEMENT_THREADSAFE_OBJ) + #define TTMATH_IMPLEMENT_THREADSAFE_OBJ /* */ + #define TTMATH_USE_THREADSAFE_OBJ(c) /* */ +#endif + } // namespace #endif // headerfilettmathmathttconfig diff --git a/ttmath/ttmathobjects.h b/ttmath/ttmathobjects.h index 2dcdfad..2dd0620 100644 --- a/ttmath/ttmathobjects.h +++ b/ttmath/ttmathobjects.h @@ -487,6 +487,7 @@ public: return false; } + TTMATH_IMPLEMENT_THREADSAFE_OBJ }; // end of class History