Import Geant4 11.0.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2021-06-25 16:12:29 +02:00
parent c968e26a39
commit 6399a014b6
4200 changed files with 207479 additions and 237366 deletions
+59 -60
View File
@@ -85,7 +85,7 @@
# endif
#endif
#if defined(G4UNIX)
#if defined(G4UNIX) && !defined(WIN32)
# include <cxxabi.h>
# include <execinfo.h>
# include <unistd.h>
@@ -202,11 +202,11 @@ inline G4String G4Demangle()
# include <algorithm>
# include <array>
# include <cstdlib>
# include <cstdio>
# include <functional>
# include <iomanip>
# include <iostream>
# include <map>
# include <mutex>
# include <regex>
# include <set>
# include <sstream>
@@ -230,7 +230,6 @@ class G4Backtrace
using id_entry_t = std::tuple<std::string, int, std::string>;
using id_list_t = std::vector<id_entry_t>;
std::shared_ptr<std::mutex> lock = std::make_shared<std::mutex>();
std::map<int, bool> is_active = {};
std::map<int, sigaction_t> current = {};
std::map<int, sigaction_t> previous = {};
@@ -452,11 +451,16 @@ G4Backtrace::GetDemangled(FuncT&& func)
inline void G4Backtrace::Message(int sig, siginfo_t* sinfo, std::ostream& os)
{
std::stringstream message;
message << "\n### CAUGHT SIGNAL: " << sig << " ### ";
// try to avoid as many dynamic allocations as possible here to avoid
// overflowing the signal stack
// ignore future signals of this type
sigignore(sig);
os << "\n### CAUGHT SIGNAL: " << sig << " ### ";
if(sinfo)
message << "address: " << sinfo->si_addr << ", ";
message << Description(sig) << ". ";
os << "address: " << sinfo->si_addr << ", ";
os << Description(sig) << ". ";
if(sig == SIGSEGV)
{
@@ -465,20 +469,19 @@ inline void G4Backtrace::Message(int sig, siginfo_t* sinfo, std::ostream& os)
switch(sinfo->si_code)
{
case SEGV_MAPERR:
message << "Address not mapped to object.";
os << "Address not mapped to object.";
break;
case SEGV_ACCERR:
message << "Invalid permissions for mapped object.";
os << "Invalid permissions for mapped object.";
break;
default:
message << "Unknown segmentation fault error: " << sinfo->si_code
<< ".";
os << "Unknown segmentation fault error: " << sinfo->si_code << ".";
break;
}
}
else
{
message << "Segmentation fault (unknown).";
os << "Segmentation fault (unknown).";
}
}
else if(sig == SIGFPE)
@@ -488,93 +491,92 @@ inline void G4Backtrace::Message(int sig, siginfo_t* sinfo, std::ostream& os)
switch(sinfo->si_code)
{
case FE_DIVBYZERO:
message << "Floating point divide by zero.";
os << "Floating point divide by zero.";
break;
case FE_OVERFLOW:
message << "Floating point overflow.";
os << "Floating point overflow.";
break;
case FE_UNDERFLOW:
message << "Floating point underflow.";
os << "Floating point underflow.";
break;
case FE_INEXACT:
message << "Floating point inexact result.";
os << "Floating point inexact result.";
break;
case FE_INVALID:
message << "Floating point invalid operation.";
os << "Floating point invalid operation.";
break;
default:
message << "Unknown floating point exception error: "
<< sinfo->si_code << ".";
os << "Unknown floating point exception error: " << sinfo->si_code
<< ".";
break;
}
}
else
{
message << "Unknown floating point exception";
os << "Unknown floating point exception";
if(sinfo)
message << ": " << sinfo->si_code;
message << ". ";
os << ": " << sinfo->si_code;
os << ". ";
}
}
message << std::endl;
os << '\n';
auto bt = GetMangled<256, 3>([](const char* _s) { return _s; });
char prefix[64];
snprintf(prefix, 64, "[PID=%i, TID=%i]", (int) getpid(),
(int) G4Threading::G4GetThreadId());
size_t sz = 0;
for(auto& itr : bt)
{
if(!itr)
break;
if(strlen(itr) == 0)
break;
++sz;
}
os << "\nBacktrace:\n";
auto _w = std::log10(sz) + 1;
for(size_t i = 0; i < sz; ++i)
{
os << prefix << "[" << std::setw(_w) << std::right << i << '/'
<< std::setw(_w) << std::right << sz << "]> " << std::left << bt.at(i)
<< '\n';
}
os << std::flush;
// exit action could cause more signals to be raise so make sure this is done
// after the message has been printed
try
{
sigignore(sig);
ExitAction(sig);
} catch(std::exception& e)
{
std::cerr << "ExitAction(" << sig << ") threw an exception" << std::endl;
std::cerr << e.what() << std::endl;
}
auto bt = GetDemangled<256, 3>(FrameFunctor());
std::stringstream prefix;
prefix << "[PID=" << getpid() << ", TID=" << G4Threading::G4GetThreadId()
<< "]";
std::vector<G4String> btvec;
for(auto& itr : bt)
{
if(itr.length() > 0)
btvec.emplace_back(std::move(itr));
}
std::stringstream serr;
serr << "\nBacktrace:\n";
auto _w = std::log10(btvec.size()) + 1;
for(size_t i = 0; i < btvec.size(); ++i)
{
serr << prefix.str() << "[" << std::setw(_w) << std::right << i << '/'
<< std::setw(_w) << std::right << btvec.size() << "]> " << std::left
<< btvec.at(i) << '\n';
}
os << serr.str().c_str() << '\n';
os << message.str() << std::flush;
}
//----------------------------------------------------------------------------//
inline void G4Backtrace::Handler(int sig, siginfo_t* sinfo, void*)
{
std::unique_lock<std::mutex> lk{ *(GetData().lock) };
Message(sig, sinfo, std::cerr);
{
std::stringstream msg;
Message(sig, sinfo, msg);
std::cerr << msg.str() << std::flush;
}
std::stringstream msg;
msg << "\n\n";
char msg[1024];
snprintf(msg, 1024, "%s", "\n");
if(sinfo && G4PSIGINFO_AVAILABLE > 0)
{
# if G4PSIGINFO_AVAILABLE > 0
psiginfo(sinfo, msg.str().c_str());
psiginfo(sinfo, msg);
fflush(stdout);
fflush(stderr);
# endif
}
else
{
std::cerr << msg.str() << std::endl;
std::cerr << msg << std::flush;
}
// ignore any termination signals
@@ -589,7 +591,6 @@ inline void G4Backtrace::Handler(int sig, siginfo_t* sinfo, void*)
inline int G4Backtrace::Enable(const signal_set_t& _signals)
{
static bool _first = true;
std::unique_lock<std::mutex> lk{ *(GetData().lock) };
if(_first)
{
std::string _msg = "!!! G4Backtrace is activated !!!";
@@ -654,8 +655,6 @@ inline int G4Backtrace::Enable(const std::string& _signals)
inline int G4Backtrace::Disable(signal_set_t _signals)
{
std::unique_lock<std::mutex> lk{ *(GetData().lock) };
if(_signals.empty())
{
for(auto& itr : GetData().is_active)
@@ -22,24 +22,33 @@
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4PhysicsLnVector
//
// Description:
//
// A physics vector which has values of energy-loss, cross-section,
// and other physics values of a particle in matter in a given
// range of energy, momentum, etc. The scale of energy/momentum
// bins is natural logarithmic.
// Author:
// - 27 April 1999, M.G. Pia: Created, copying from G4PhysicsLogVector
// --------------------------------------------------------------------
#ifndef G4PhysicsLnVector_hh
#define G4PhysicsLnVector_hh 1
#include "G4PhysicsLogVector.hh"
using G4PhysicsLnVector = G4PhysicsLogVector;
#ifndef G4FILESYSTEM_HH
#define G4FILESYSTEM_HH
/**
* @namespace G4fs
* Namespace adapter for `filesystem` in `std::` or `std::experimental::`
*
* Developers should use this namespace to scope into the C++ filesystem
* library, e.g.
*
* ```cpp
* // Don't use std:: directly...
* auto p = std::filesystem::path{ argv[0] };
*
* // ... use the alias
* auto p = G4fs::path{ argv[0] };
* ```
*
* This allows compatibility with C++ standard libraries that only provide
* `filesystem` in the `std::experimental` namespace
*
*/
#if __has_include(<filesystem>)
# include <filesystem>
namespace G4fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
# include <experimental/filesystem>
namespace G4fs = std::experimental::filesystem;
#endif
#endif /* G4FILESYSTEM_HH */
@@ -1,66 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4LPhysicsFreeVector
//
// Class description:
//
// Derived from base class G4PhysicsVector
// This is a free vector for Low Energy Physics cross section data.
// The class name includes an "L" to distinguish it from other groups
// who may wish to implement a free vector in a different way.
// A subdivision method is used to find the energy|momentum bin.
// Author: F.W. Jones (TRIUMF), 04-June-1996 - First implementation
// --------------------------------------------------------------------
#ifndef G4LPhysicsFreeVector_hh
#define G4LPhysicsFreeVector_hh 1
#include "G4PhysicsFreeVector.hh"
class G4LPhysicsFreeVector : public G4PhysicsFreeVector
{
public:
G4LPhysicsFreeVector();
// The vector will be filled from external file using Retrieve method
G4LPhysicsFreeVector(std::size_t length, G4double emin = 0.,
G4double emax = 0.);
// The vector with 'length' elements will be filled using PutValues
// method by default the vector is initialized with zeros
virtual ~G4LPhysicsFreeVector();
inline void PutValues(std::size_t index, G4double e, G4double dataValue);
// User code is responsible for correct filling of all elements
};
inline void G4LPhysicsFreeVector::PutValues(std::size_t index, G4double e,
G4double value)
{
G4PhysicsFreeVector::PutValue(index, e, value);
}
#endif
@@ -66,6 +66,8 @@ using CLHEP::STP_Pressure;
using CLHEP::STP_Temperature;
using CLHEP::twopi;
using CLHEP::twopi_mc2_rcl2;
using CLHEP::Bohr_magneton;
using CLHEP::nuclear_magneton;
using CLHEP::universe_mean_density;
#endif
@@ -40,57 +40,94 @@
// - 06 Jun. 1996, K.Amako: Implemented the 1st version
// Revisions:
// - 11 Nov. 2000, H.Kurashige: Use STL vector for dataVector and binVector
// - 04 Feb. 2021, V.Ivanchenko moved implementation of all free vectors
// to this class
// --------------------------------------------------------------------
#ifndef G4PhysicsFreeVector_hh
#define G4PhysicsFreeVector_hh 1
#include "G4DataVector.hh"
#include "G4PhysicsVector.hh"
#include "globals.hh"
#include <vector>
class G4PhysicsFreeVector : public G4PhysicsVector
{
public:
G4PhysicsFreeVector();
// The vector will be filled from external file using Retrieve() method
public:
explicit G4PhysicsFreeVector(std::size_t length = 0, G4bool spline = false);
explicit G4PhysicsFreeVector(std::size_t length, G4double emin,
G4double emax, G4bool spline = false);
// The vector with 'length' elements will be filled using the PutValues(..)
// method; energy and data vectors are initialized with zeros.
explicit G4PhysicsFreeVector(std::size_t length);
// The vector with 'length' elements will be filled using PutValue()
// method; by default the vector is initialized with zeros
G4PhysicsFreeVector(const G4DataVector& eVector,
const G4DataVector& dataVector);
// The vector is filled in this constructor.
// 'eVector' and 'dataVector' need to have the same vector length
// 'eVector' assumed to be ordered
explicit G4PhysicsFreeVector(const std::vector<G4double>& energies,
const std::vector<G4double>& values,
G4bool spline = false);
// The vector is filled in this constructor;
// 'energies' and 'values' need to have the same vector length;
// 'energies' assumed to be ordered and controlled in the user code.
explicit G4PhysicsFreeVector(const G4double* energies, const G4double* values,
std::size_t length, G4bool spline = false);
// The vector is filled in this constructor;
// 'energies' and 'values' need to have the same vector length;
// 'energies' assumed to be ordered in the user code.
virtual ~G4PhysicsFreeVector();
inline void PutValue(std::size_t index, G4double energy, G4double dValue);
void PutValues(std::size_t index, G4double e, G4double value);
// User code is responsible for correct filling of all elements
void InsertValues(G4double energy, G4double value);
G4double GetEnergy(G4double value);
// This method can be applied if both energy and data values
// grow monotonically, for example, if in this vector a
// cumulative probability density function is stored.
inline G4double GetMaxValue();
inline G4double GetMinValue();
inline G4double GetMaxLowEdgeEnergy();
inline G4double GetMinLowEdgeEnergy();
// Obsolete methods
inline void PutValue(std::size_t index, G4double e, G4double value);
// User code is responsible for correct filling of all elements
// Obsolete method
private:
std::size_t FindValueBinLocation(G4double aValue);
G4double LinearInterpolationOfEnergy(G4double aValue, std::size_t locBin);
};
// -----------------------------
// Inline methods implementation
// -----------------------------
inline G4double G4PhysicsFreeVector::GetMaxValue()
{
return dataVector.back();
}
inline G4double G4PhysicsFreeVector::GetMinValue()
{
return dataVector.front();
}
inline G4double G4PhysicsFreeVector::GetMaxLowEdgeEnergy()
{
return edgeMax;
}
inline G4double G4PhysicsFreeVector::GetMinLowEdgeEnergy()
{
return edgeMin;
}
inline void G4PhysicsFreeVector::PutValue(std::size_t index, G4double e,
G4double value)
{
if(index >= numberOfNodes)
{
PrintPutValueError(index);
}
binVector[index] = e;
dataVector[index] = value;
if(index == 0)
{
edgeMin = e;
}
else if(numberOfNodes - 1 == index)
{
edgeMax = e;
}
PutValues(index, e, value);
}
#endif
@@ -46,11 +46,12 @@
class G4PhysicsLinearVector : public G4PhysicsVector
{
public:
G4PhysicsLinearVector();
public:
explicit G4PhysicsLinearVector(G4bool spline = false);
// The vector will be filled from external file using Retrieve() method
G4PhysicsLinearVector(G4double Emin, G4double Emax, std::size_t Nbin);
explicit G4PhysicsLinearVector(G4double Emin, G4double Emax, std::size_t Nbin,
G4bool spline = false);
// Energy vector will be computed and filled at construction,
// number of elements 'Nbin+1'. Use PutValue() to fill the data vector
@@ -46,11 +46,12 @@
class G4PhysicsLogVector : public G4PhysicsVector
{
public:
G4PhysicsLogVector();
public:
explicit G4PhysicsLogVector(G4bool spline = false);
// The vector will be filled from external file using Retrieve() method
G4PhysicsLogVector(G4double Emin, G4double Emax, std::size_t Nbin);
explicit G4PhysicsLogVector(G4double Emin, G4double Emax, std::size_t Nbin,
G4bool spline = false);
// Energy vector will be computed and filled at construction,
// number of nodes 'Nbin+1'. Use PutValue() to fill the data vector
// Because of logarithmic scale, 'Emin' has to be
@@ -1,106 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4PhysicsOrderedFreeVector
//
// Class description:
//
// A physics ordered free vector inherits from G4PhysicsVector which
// has values of energy-loss, cross-section, and other physics values
// of a particle in matter in a given range of energy, momentum, etc.).
// In addition, the ordered free vector provides a method for
// the user to insert energy/value pairs in sequence. Methods to
// retrieve the Max and Min energies and values from the vector are
// also provided.
// Author: Juliet Armstrong (TRIUMF), 13 August 1996
// Revisions:
// - 11.11.2000, H.Kurashige: use STL vector for dataVector and binVector
// --------------------------------------------------------------------
#ifndef G4PhysicsOrderedFreeVector_hh
#define G4PhysicsOrderedFreeVector_hh 1
#include "G4PhysicsVector.hh"
class G4PhysicsOrderedFreeVector : public G4PhysicsVector
{
public:
G4PhysicsOrderedFreeVector();
// The vector will be filled from extern file using Retrieve()
// or InsertValues() methods
G4PhysicsOrderedFreeVector(const std::vector<G4double>& Energies,
const std::vector<G4double>& Values);
G4PhysicsOrderedFreeVector(G4double* Energies, G4double* Values,
std::size_t VectorLength);
// The vector is filled in this constructor.
// 'Energies' and 'Values' need to have the same vector length
// 'Energies' assumed to be ordered
virtual ~G4PhysicsOrderedFreeVector();
void InsertValues(G4double energy, G4double value);
G4double GetEnergy(G4double aValue);
inline G4double GetMaxValue();
inline G4double GetMinValue();
inline G4double GetMaxLowEdgeEnergy();
inline G4double GetMinLowEdgeEnergy();
private:
std::size_t FindValueBinLocation(G4double aValue);
G4double LinearInterpolationOfEnergy(G4double aValue, std::size_t locBin);
};
// -----------------------------
// Inline methods implementation
// -----------------------------
inline G4double G4PhysicsOrderedFreeVector::GetMaxValue()
{
return dataVector.back();
}
inline G4double G4PhysicsOrderedFreeVector::GetMinValue()
{
return dataVector.front();
}
inline G4double G4PhysicsOrderedFreeVector::GetMaxLowEdgeEnergy()
{
return binVector.back();
}
inline G4double G4PhysicsOrderedFreeVector::GetMinLowEdgeEnergy()
{
return binVector.front();
}
#endif
@@ -100,7 +100,7 @@ class G4PhysicsTable : public std::vector<G4PhysicsVector*>
G4bool StorePhysicsTable(const G4String& filename, G4bool ascii = false);
// Stores PhysicsTable in a file (returns false in case of failure)
G4bool RetrievePhysicsTable(const G4String& filename, G4bool ascii = false);
G4bool RetrievePhysicsTable(const G4String& filename, G4bool ascii = false, G4bool spline = false);
// Retrieves Physics from a file (returns false in case of failure)
void ResetFlagArray();
@@ -115,7 +115,7 @@ class G4PhysicsTable : public std::vector<G4PhysicsVector*>
friend std::ostream& operator<<(std::ostream& out, G4PhysicsTable& table);
protected:
G4PhysicsVector* CreatePhysicsVector(G4int type);
G4PhysicsVector* CreatePhysicsVector(G4int type, G4bool spline);
G4FlagCollection vecFlag;
};
@@ -179,6 +179,9 @@ class G4PhysicsVector
inline void SetSpline(G4bool);
// Activate/deactivate Spline interpolation
inline G4bool GetSpline() const;
// True if using spline interpolation
G4bool Store(std::ofstream& fOut, G4bool ascii = false) const;
virtual G4bool Retrieve(std::ifstream& fIn, G4bool ascii = false);
// To store/retrieve persistent data to/from file streams.
@@ -194,7 +197,7 @@ class G4PhysicsVector
void CopyData(const G4PhysicsVector& vec);
// Internal methods for allowing copy of objects
void PrintPutValueError(std::size_t index);
void PrintPutValueError(std::size_t index, G4double e1, G4double e2);
G4PhysicsVectorType type = T_G4PhysicsVector;
// The type of PhysicsVector (enumerator)
@@ -66,7 +66,7 @@ inline void G4PhysicsVector::PutValue(std::size_t index, G4double theValue)
{
if(index >= numberOfNodes)
{
PrintPutValueError(index);
PrintPutValueError(index, theValue, theValue);
}
dataVector[index] = theValue;
}
@@ -104,6 +104,10 @@ inline void G4PhysicsVector::SetSpline(G4bool val)
// ---------------------------------------------------------------
inline G4bool G4PhysicsVector::GetSpline() const { return useSpline; }
// ---------------------------------------------------------------
inline void G4PhysicsVector::SetVerboseLevel(G4int value)
{
verboseLevel = value;
@@ -46,10 +46,7 @@ enum G4PhysicsVectorType
T_G4PhysicsVector = 0,
T_G4PhysicsLinearVector,
T_G4PhysicsLogVector,
T_G4PhysicsLnVector,
T_G4PhysicsFreeVector,
T_G4PhysicsOrderedFreeVector,
T_G4LPhysicsFreeVector
T_G4PhysicsFreeVector
};
#endif
@@ -140,6 +140,11 @@ static constexpr double millisecond = 1.e-3 * second;
static constexpr double microsecond = 1.e-6 * second;
static constexpr double picosecond = 1.e-12 * second;
static constexpr double minute = 60*second;
static constexpr double hour = 60*minute;
static constexpr double day = 24*hour;
static constexpr double year = 365*day;
static constexpr double hertz = 1. / second;
static constexpr double kilohertz = 1.e+3 * hertz;
static constexpr double megahertz = 1.e+6 * hertz;
@@ -189,6 +194,7 @@ static constexpr double megaelectronvolt = 1.e+6 * electronvolt;
static constexpr double gigaelectronvolt = 1.e+9 * electronvolt;
static constexpr double teraelectronvolt = 1.e+12 * electronvolt;
static constexpr double petaelectronvolt = 1.e+15 * electronvolt;
static constexpr double millielectronvolt = 1.e-3 * electronvolt;
// symbols
static constexpr double MeV = megaelectronvolt;
@@ -51,6 +51,7 @@ using CLHEP::cm2;
using CLHEP::cm3;
using CLHEP::coulomb;
using CLHEP::curie;
using CLHEP::day;
using CLHEP::deg;
using CLHEP::degree;
using CLHEP::dL;
@@ -69,6 +70,7 @@ using CLHEP::gray;
using CLHEP::henry;
using CLHEP::hep_pascal;
using CLHEP::hertz;
using CLHEP::hour;
using CLHEP::joule;
using CLHEP::kelvin;
using CLHEP::keV;
@@ -106,6 +108,7 @@ using CLHEP::micrometer;
using CLHEP::microsecond;
using CLHEP::milliampere;
using CLHEP::millibarn;
using CLHEP::millielectronvolt;
using CLHEP::millifarad;
using CLHEP::milligram;
using CLHEP::millimeter;
@@ -113,6 +116,7 @@ using CLHEP::millimeter2;
using CLHEP::millimeter3;
using CLHEP::milliradian;
using CLHEP::millisecond;
using CLHEP::minute;
using CLHEP::mL;
using CLHEP::mm;
using CLHEP::mm2;
@@ -154,5 +158,6 @@ using CLHEP::us;
using CLHEP::volt;
using CLHEP::watt;
using CLHEP::weber;
using CLHEP::year;
#endif
@@ -95,10 +95,14 @@
#ifndef G4TLSSINGLETON_HH
#define G4TLSSINGLETON_HH 1
#include <list>
#include "G4AutoLock.hh"
#include "G4Cache.hh"
#include "G4Backtrace.hh"
#include "G4Threading.hh"
#include <list>
#include <vector>
#include <functional>
// Forward declaration. See G4AutoDelete.hh
//
@@ -108,6 +112,35 @@ namespace G4AutoDelete
void Register(T*);
}
template <class T>
class G4ThreadLocalSingleton;
// this explicit specialization holds all the callbacks
// to explicitly invoke the auto-deletion
template <>
class G4ThreadLocalSingleton<void>
{
private:
using fvector_t = std::vector<std::function<void()>>;
template <class T>
friend class G4ThreadLocalSingleton;
static fvector_t& GetCallbacks();
static G4Mutex& GetMutex();
public:
static void Clear();
template <typename FuncT>
static typename fvector_t::iterator Insert(FuncT&& _func)
{
G4AutoLock _lk{ GetMutex() };
return GetCallbacks().emplace(GetCallbacks().end(),
std::forward<FuncT>(_func));
}
};
template <class T>
class G4ThreadLocalSingleton : private G4Cache<T*>
{
@@ -119,11 +152,16 @@ class G4ThreadLocalSingleton : private G4Cache<T*>
~G4ThreadLocalSingleton();
G4ThreadLocalSingleton(const G4ThreadLocalSingleton&) = delete;
G4ThreadLocalSingleton(G4ThreadLocalSingleton&&) = default;
G4ThreadLocalSingleton& operator=(const G4ThreadLocalSingleton&) = delete;
G4ThreadLocalSingleton& operator=(G4ThreadLocalSingleton&&) = default;
T* Instance() const;
// Returns a pointer to a thread-private instance of T
private:
G4ThreadLocalSingleton(G4ThreadLocalSingleton& rhs);
void Register(T* i) const;
void Clear();
@@ -142,6 +180,23 @@ G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton()
{
G4MUTEXINIT(listm);
G4Cache<T*>::Put(static_cast<T*>(0));
// Uncomment below to find the origin of where instantiation happened
/*
auto bt = G4Backtrace::GetDemangled<4, 1>(
[](const char* cstr) { return std::string{ cstr }; });
std::cout << "Backtrace to G4ThreadLocalSingleton<"
<< G4Demangle<T>().c_str() << ">:\n";
for(auto& itr : bt)
{
if(!itr.empty())
std::cout << "\t" << itr << "\n";
}
*/
G4ThreadLocalSingleton<void>::Insert([&]() {
printf("Deleting G4ThreadLocalSingletons for type %s ...\n",
G4Demangle<T>().c_str());
this->Clear();
});
}
template <class T>
@@ -164,10 +219,6 @@ T* G4ThreadLocalSingleton<T>::Instance() const
return instance;
}
template <class T>
G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton(G4ThreadLocalSingleton&)
{}
template <class T>
void G4ThreadLocalSingleton<T>::Register(T* i) const
{
@@ -178,6 +229,8 @@ void G4ThreadLocalSingleton<T>::Register(T* i) const
template <class T>
void G4ThreadLocalSingleton<T>::Clear()
{
if(instances.empty())
return;
G4AutoLock l(&listm);
while(!instances.empty())
{
@@ -40,11 +40,11 @@
// |--> patch number
#ifndef G4VERSION_NUMBER
#define G4VERSION_NUMBER 1072
#define G4VERSION_NUMBER 1100
#endif
#ifndef G4VERSION_TAG
#define G4VERSION_TAG "$Name: geant4-10-07-patch-02 $"
#define G4VERSION_TAG "$Name: geant4-11-00-beta-01 $"
#endif
// as variables
@@ -53,10 +53,10 @@
#include "G4Types.hh"
#ifdef G4MULTITHREADED
static const G4String G4Version = "$Name: geant4-10-07-patch-02 [MT]$";
static const G4String G4Version = "$Name: geant4-11-00-beta-01 [MT]$";
#else
static const G4String G4Version = "$Name: geant4-10-07-patch-02 $";
static const G4String G4Version = "$Name: geant4-11-00-beta-01 $";
#endif
static const G4String G4Date = "(11-June-2021)";
static const G4String G4Date = "(25-June-2021)";
#endif