Update comments in integer.cpp
parent
81f8c48faf
commit
a65cf70ff8
50
integer.cpp
50
integer.cpp
|
|
@ -1,32 +1,44 @@
|
||||||
// integer.cpp - originally written and placed in the public domain by Wei Dai
|
// integer.cpp - originally written and placed in the public domain by Wei Dai
|
||||||
// contains public domain code contributed by Alister Lee and Leonard Janke
|
// contains public domain code contributed by Alister Lee and Leonard Janke
|
||||||
|
|
||||||
// Notes by JW: The Integer class needs to do two things. First, it needs to set function
|
// Notes by JW: The Integer class needs to do two things. First, it needs
|
||||||
// pointers on some platforms, like X86 and X64. The function pointers select a fast multiply
|
// to set function pointers on some platforms, like X86 and X64. The
|
||||||
// and addition based on the cpu. Second, it wants to create Integer::Zero(), Integer::One()
|
// function pointers select a fast multiply and addition based on the cpu.
|
||||||
// and Integer::Two().
|
// Second, it wants to create Integer::Zero(), Integer::One() and
|
||||||
|
// Integer::Two().
|
||||||
// The function pointers are initialized in the InitializeInteger class by
|
// The function pointers are initialized in the InitializeInteger class by
|
||||||
// calling SetFunctionPointers(). The call to SetFunctionPointers() is
|
// calling SetFunctionPointers(). The call to SetFunctionPointers() is
|
||||||
// guarded to run once using a double-checked pattern. We don't use C++
|
// guarded to run once using a double-checked pattern. We don't use C++
|
||||||
// std::call_once due to bad interactions between libstdc++, glibc and
|
// std::call_once due to bad interactions between libstdc++, glibc and
|
||||||
// pthreads. Since they are only function pointers we don't have to worry
|
// pthreads. The bad interactions were causing crashes for us on platforms
|
||||||
// about leaking memory. The worst case seems to be the pointer gets written
|
// like Sparc and PowerPC. Since we are only setting function pointers we
|
||||||
// twice.
|
// don't have to worry about leaking memory. The worst case seems to be the
|
||||||
// For Integer::Zero(), Integer::One() and Integer::Two(), we use one of two
|
// pointers gets written twice until the init flag is set and visible to
|
||||||
// strategies. First, if C++11 dynamic initialization is available, then we
|
// all threads.
|
||||||
// use a static variable. Second, if C++11 dynamic initialization is not
|
// For Integer::Zero(), Integer::One() and Integer::Two(), we use one of three
|
||||||
// available, then we fall back to Wei's original code of a Singleton.
|
// strategies. First, if initialization priorities are available then we use
|
||||||
// Wei's original code was much simpler. It simply used the Singleton pattern,
|
// them. Initialization priorities are init_priority() on Linux and init_seg()
|
||||||
// but it always produced memory findings on some platforms. The Singleton
|
// on Windows. AIX, OS X and several other platforms lack them. Initialization
|
||||||
// generates memory findings because it uses a Create On First Use pattern
|
// priorities are platform specific but they are also the most trouble free
|
||||||
// (a dumb Nifty Counter) and the compiler had to be smart enough to fold
|
// with determisitic destruction.
|
||||||
// them to return the same object. Unix and Linux compilers do a good job of
|
// Second, if C++11 dynamic initialization is available, then we use it. After
|
||||||
// folding objects, but Microsoft compilers do a rather poor job for some
|
// the std::call_once fiasco we dropped the priority dynamic initialization
|
||||||
// versions of the compilers.
|
// to avoid unknown troubles platforms that are tested less frequently. In
|
||||||
|
// addition Microsoft platforms mostly do not provide dynamic initialization.
|
||||||
|
// The MSDN docs claim they do but they don't in practice because we need
|
||||||
|
// Visual Studio 2017 and Windows 10 or above.
|
||||||
|
// Third, we fall back to Wei's original code of a Singleton. Wei's original
|
||||||
|
// code was much simpler. It simply used the Singleton pattern, but it always
|
||||||
|
// produced memory findings on some platforms. The Singleton generates memory
|
||||||
|
// findings because it uses a Create On First Use pattern (a dumb Nifty
|
||||||
|
// Counter) and the compiler had to be smart enough to fold them to return
|
||||||
|
// the same object. Unix and Linux compilers do a good job of folding objects,
|
||||||
|
// but Microsoft compilers do a rather poor job for some versions of the
|
||||||
|
// compiler.
|
||||||
// Another problem with the Singleton is resource destruction requires running
|
// Another problem with the Singleton is resource destruction requires running
|
||||||
// resource acquisition in reverse. For resources provided through the
|
// resource acquisition in reverse. For resources provided through the
|
||||||
// Singletons, there is no way to express the dependency order to safely
|
// Singletons, there is no way to express the dependency order to safely
|
||||||
// destroy resources. (That's one of the problems C++11 dynamic00
|
// destroy resources. (That's one of the problems C++11 dynamic
|
||||||
// intitialization with concurrent execution is supposed to solve).
|
// intitialization with concurrent execution is supposed to solve).
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue