Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/intercoms/src/G4GenericMessenger.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /intercoms/src/G4GenericMessenger.cc (Version 11.3.0) and /intercoms/src/G4GenericMessenger.cc (Version 11.2)


  1 // *******************************************      1 // ********************************************************************
  2 // * License and Disclaimer                         2 // * License and Disclaimer                                           *
  3 // *                                                3 // *                                                                  *
  4 // * The  Geant4 software  is  copyright of th      4 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  5 // * the Geant4 Collaboration.  It is provided      5 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  6 // * conditions of the Geant4 Software License      6 // * conditions of the Geant4 Software License,  included in the file *
  7 // * LICENSE and available at  http://cern.ch/      7 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  8 // * include a list of copyright holders.           8 // * include a list of copyright holders.                             *
  9 // *                                                9 // *                                                                  *
 10 // * Neither the authors of this software syst     10 // * Neither the authors of this software system, nor their employing *
 11 // * institutes,nor the agencies providing fin     11 // * institutes,nor the agencies providing financial support for this *
 12 // * work  make  any representation or  warran     12 // * work  make  any representation or  warranty, express or implied, *
 13 // * regarding  this  software system or assum     13 // * regarding  this  software system or assume any liability for its *
 14 // * use.  Please see the license in the file      14 // * use.  Please see the license in the file  LICENSE  and URL above *
 15 // * for the full disclaimer and the limitatio     15 // * for the full disclaimer and the limitation of liability.         *
 16 // *                                               16 // *                                                                  *
 17 // * This  code  implementation is the result      17 // * This  code  implementation is the result of  the  scientific and *
 18 // * technical work of the GEANT4 collaboratio     18 // * technical work of the GEANT4 collaboration.                      *
 19 // * By using,  copying,  modifying or  distri     19 // * By using,  copying,  modifying or  distributing the software (or *
 20 // * any work based  on the software)  you  ag     20 // * any work based  on the software)  you  agree  to acknowledge its *
 21 // * use  in  resulting  scientific  publicati     21 // * use  in  resulting  scientific  publications,  and indicate your *
 22 // * acceptance of all terms of the Geant4 Sof     22 // * acceptance of all terms of the Geant4 Software license.          *
 23 // *******************************************     23 // ********************************************************************
 24 //                                                 24 //
 25 // G4GenericMessenger                              25 // G4GenericMessenger
 26 //                                                 26 //
 27 // Author:                                         27 // Author:
 28 //    P.Mato, CERN - 27 September 2012             28 //    P.Mato, CERN - 27 September 2012
 29 // Updates:                                        29 // Updates:
 30 //    M.Asai, SLAC - 26 November 2013              30 //    M.Asai, SLAC - 26 November 2013
 31 //      Adding methods with unit declaration a     31 //      Adding methods with unit declaration and making thread-safe for
 32 //      version 10.                                32 //      version 10.
 33 //    M.Asai, SLAC - 04 May 2014                   33 //    M.Asai, SLAC - 04 May 2014
 34 //      Fix core dump when GetCurrentValue() m     34 //      Fix core dump when GetCurrentValue() method is invoked for
 35 //      a command defined by DeclareMethod().      35 //      a command defined by DeclareMethod().
 36 //    M.Asai, SLAC - 30 September 2020         << 
 37 //      Adding new parameter type 'L' for long << 
 38 //    M.Asai, SLAC - 11 July 2021                  36 //    M.Asai, SLAC - 11 July 2021
 39 //      Adding G4ThreeVector type without unit     37 //      Adding G4ThreeVector type without unit
 40 //    M.Asai, JLab - 24 April 2024             << 
 41 //      Fix DeclareMethod() wrongly converts v << 
 42 // -------------------------------------------     38 // --------------------------------------------------------------------
 43                                                    39 
 44 #include "G4GenericMessenger.hh"                   40 #include "G4GenericMessenger.hh"
 45                                                    41 
 46 #include "G4Threading.hh"                          42 #include "G4Threading.hh"
 47 #include "G4Types.hh"                              43 #include "G4Types.hh"
 48 #include "G4UIcmdWithABool.hh"                 << 
 49 #include "G4UIcmdWith3Vector.hh"                   44 #include "G4UIcmdWith3Vector.hh"
 50 #include "G4UIcmdWith3VectorAndUnit.hh"            45 #include "G4UIcmdWith3VectorAndUnit.hh"
 51 #include "G4UIcmdWithADoubleAndUnit.hh"            46 #include "G4UIcmdWithADoubleAndUnit.hh"
 52 #include "G4UIcommand.hh"                          47 #include "G4UIcommand.hh"
 53 #include "G4UIdirectory.hh"                        48 #include "G4UIdirectory.hh"
 54 #include "G4UImessenger.hh"                        49 #include "G4UImessenger.hh"
 55 #include "G4Tokenizer.hh"                      << 
 56                                                    50 
 57 #include <iostream>                                51 #include <iostream>
 58                                                    52 
 59 class G4InvalidUICommand : public std::bad_cas     53 class G4InvalidUICommand : public std::bad_cast
 60 {                                                  54 {
 61   public:                                          55   public:
 62     G4InvalidUICommand() = default;                56     G4InvalidUICommand() = default;
 63     const char* what() const throw() override      57     const char* what() const throw() override
 64     {                                              58     {
 65       return "G4InvalidUICommand: command does     59       return "G4InvalidUICommand: command does not exist or is of invalid type";
 66     }                                              60     }
 67 };                                                 61 };
 68                                                    62 
 69 G4GenericMessenger::G4GenericMessenger(void* o     63 G4GenericMessenger::G4GenericMessenger(void* obj, const G4String& dir, const G4String& doc)
 70   : directory(dir), object(obj)                    64   : directory(dir), object(obj)
 71 {                                                  65 {
 72   dircmd = new G4UIdirectory(dir);                 66   dircmd = new G4UIdirectory(dir);
 73   dircmd->SetGuidance(doc);                        67   dircmd->SetGuidance(doc);
 74 }                                                  68 }
 75                                                    69 
 76 G4GenericMessenger::~G4GenericMessenger()          70 G4GenericMessenger::~G4GenericMessenger()
 77 {                                                  71 {
 78   delete dircmd;                                   72   delete dircmd;
 79   for (const auto& propertie : properties) {       73   for (const auto& propertie : properties) {
 80     delete propertie.second.command;               74     delete propertie.second.command;
 81   }                                                75   }
 82   for (const auto& method : methods) {             76   for (const auto& method : methods) {
 83     delete method.second.command;                  77     delete method.second.command;
 84   }                                                78   }
 85 }                                                  79 }
 86                                                    80 
 87 G4GenericMessenger::Command&                       81 G4GenericMessenger::Command&
 88 G4GenericMessenger::DeclareProperty(const G4St     82 G4GenericMessenger::DeclareProperty(const G4String& name, const G4AnyType& var, const G4String& doc)
 89 {                                                  83 {
 90   G4String fullpath = directory + name;            84   G4String fullpath = directory + name;
 91   G4UIcommand* cmd = nullptr;                      85   G4UIcommand* cmd = nullptr;
 92   if (var.TypeInfo() == typeid(G4ThreeVector))     86   if (var.TypeInfo() == typeid(G4ThreeVector)) {
 93     cmd = new G4UIcmdWith3Vector(fullpath.c_st     87     cmd = new G4UIcmdWith3Vector(fullpath.c_str(), this);
 94     (static_cast<G4UIcmdWith3Vector*>(cmd))        88     (static_cast<G4UIcmdWith3Vector*>(cmd))
 95       ->SetParameterName("valueX", "valueY", "     89       ->SetParameterName("valueX", "valueY", "valueZ", false, false);
 96   }                                                90   }
 97   else {                                           91   else {
 98     cmd = new G4UIcommand(fullpath.c_str(), th     92     cmd = new G4UIcommand(fullpath.c_str(), this);
 99     char ptype;                                    93     char ptype;
100     if (var.TypeInfo() == typeid(int) || var.T     94     if (var.TypeInfo() == typeid(int) || var.TypeInfo() == typeid(long)
101         || var.TypeInfo() == typeid(unsigned i     95         || var.TypeInfo() == typeid(unsigned int) || var.TypeInfo() == typeid(unsigned long))
102     {                                              96     {
103       ptype = 'i';                                 97       ptype = 'i';
104     }                                              98     }
105     else if (var.TypeInfo() == typeid(float) |     99     else if (var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double)) {
106       ptype = 'd';                                100       ptype = 'd';
107     }                                             101     }
108     else if (var.TypeInfo() == typeid(bool)) {    102     else if (var.TypeInfo() == typeid(bool)) {
109       ptype = 'b';                                103       ptype = 'b';
110     }                                             104     }
111     else if (var.TypeInfo() == typeid(G4String    105     else if (var.TypeInfo() == typeid(G4String)) {
112       ptype = 's';                                106       ptype = 's';
113     }                                             107     }
114     else {                                        108     else {
115       ptype = 's';                                109       ptype = 's';
116     }                                             110     }
117     cmd->SetParameter(new G4UIparameter("value    111     cmd->SetParameter(new G4UIparameter("value", ptype, false));
118   }                                               112   }
119   if (!doc.empty()) {                             113   if (!doc.empty()) {
120     cmd->SetGuidance(doc);                        114     cmd->SetGuidance(doc);
121   }                                               115   }
122   return properties[name] = Property(var, cmd)    116   return properties[name] = Property(var, cmd);
123 }                                                 117 }
124                                                   118 
125 G4GenericMessenger::Command&                      119 G4GenericMessenger::Command&
126 G4GenericMessenger::DeclarePropertyWithUnit(co    120 G4GenericMessenger::DeclarePropertyWithUnit(const G4String& name, const G4String& defaultUnit,
127                                             co    121                                             const G4AnyType& var, const G4String& doc)
128 {                                                 122 {
129   if (var.TypeInfo() != typeid(float) && var.T    123   if (var.TypeInfo() != typeid(float) && var.TypeInfo() != typeid(double)
130       && var.TypeInfo() != typeid(G4ThreeVecto    124       && var.TypeInfo() != typeid(G4ThreeVector))
131   {                                               125   {
132     return DeclareProperty(name, var, doc);       126     return DeclareProperty(name, var, doc);
133   }                                               127   }
134   G4String fullpath = directory + name;           128   G4String fullpath = directory + name;
135   G4UIcommand* cmd;                               129   G4UIcommand* cmd;
136   if (var.TypeInfo() == typeid(float) || var.T    130   if (var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double)) {
137     cmd = new G4UIcmdWithADoubleAndUnit(fullpa    131     cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
138     (static_cast<G4UIcmdWithADoubleAndUnit*>(c    132     (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetParameterName("value", false, false);
139     (static_cast<G4UIcmdWithADoubleAndUnit*>(c    133     (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
140   }                                               134   }
141   else {                                          135   else {
142     cmd = new G4UIcmdWith3VectorAndUnit(fullpa    136     cmd = new G4UIcmdWith3VectorAndUnit(fullpath.c_str(), this);
143     (static_cast<G4UIcmdWith3VectorAndUnit*>(c    137     (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))
144       ->SetParameterName("valueX", "valueY", "    138       ->SetParameterName("valueX", "valueY", "valueZ", false, false);
145     (static_cast<G4UIcmdWith3VectorAndUnit*>(c    139     (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
146   }                                               140   }
147                                                   141 
148   if (!doc.empty()) {                             142   if (!doc.empty()) {
149     cmd->SetGuidance(doc);                        143     cmd->SetGuidance(doc);
150   }                                               144   }
151   return properties[name] = Property(var, cmd)    145   return properties[name] = Property(var, cmd);
152 }                                                 146 }
153                                                   147 
154 G4GenericMessenger::Command&                      148 G4GenericMessenger::Command&
155 G4GenericMessenger::DeclareMethod(const G4Stri    149 G4GenericMessenger::DeclareMethod(const G4String& name, const G4AnyMethod& fun, const G4String& doc)
156 {                                                 150 {
157   G4String fullpath = directory + name;           151   G4String fullpath = directory + name;
158   auto* cmd = new G4UIcommand(fullpath.c_str()    152   auto* cmd = new G4UIcommand(fullpath.c_str(), this);
159   if (!doc.empty()) {                             153   if (!doc.empty()) {
160     cmd->SetGuidance(doc);                        154     cmd->SetGuidance(doc);
161   }                                               155   }
162   for (std::size_t i = 0; i < fun.NArg(); ++i)    156   for (std::size_t i = 0; i < fun.NArg(); ++i) {
163     G4String argNam = "arg" + ItoS((G4int)i);     157     G4String argNam = "arg" + ItoS((G4int)i);
164     char ptype = 's';                             158     char ptype = 's';
165     auto& tInfo = fun.ArgType(i);                 159     auto& tInfo = fun.ArgType(i);
166     if (tInfo == typeid(int) || tInfo == typei    160     if (tInfo == typeid(int) || tInfo == typeid(long) || tInfo == typeid(unsigned int)
167         || tInfo == typeid(unsigned long))        161         || tInfo == typeid(unsigned long))
168     {                                             162     {
169       ptype = 'i';                                163       ptype = 'i';
170     }                                             164     }
171     else if (tInfo == typeid(float) || tInfo =    165     else if (tInfo == typeid(float) || tInfo == typeid(double)) {
172       ptype = 'd';                                166       ptype = 'd';
173     }                                             167     }
174     else if (tInfo == typeid(bool)) {             168     else if (tInfo == typeid(bool)) {
175       ptype = 'b';                                169       ptype = 'b';
176     }                                             170     }
177     else if (tInfo == typeid(G4String)) {         171     else if (tInfo == typeid(G4String)) {
178       ptype = 's';                                172       ptype = 's';
179     }                                             173     }
180     else {                                        174     else {
181       ptype = 's';                                175       ptype = 's';
182     }                                             176     }
183     cmd->SetParameter(new G4UIparameter(argNam    177     cmd->SetParameter(new G4UIparameter(argNam, ptype, false));
184   }                                               178   }
185   return methods[name] = Method(fun, object, c    179   return methods[name] = Method(fun, object, cmd);
186 }                                                 180 }
187                                                   181 
188 G4GenericMessenger::Command& G4GenericMessenge    182 G4GenericMessenger::Command& G4GenericMessenger::DeclareMethodWithUnit(const G4String& name,
189                                                   183                                                                        const G4String& defaultUnit,
190                                                   184                                                                        const G4AnyMethod& fun,
191                                                   185                                                                        const G4String& doc)
192 {                                                 186 {
193   G4String fullpath = directory + name;           187   G4String fullpath = directory + name;
194   if (fun.NArg() != 1) {                          188   if (fun.NArg() != 1) {
195     G4ExceptionDescription ed;                    189     G4ExceptionDescription ed;
196     ed << "G4GenericMessenger::DeclareMethodWi    190     ed << "G4GenericMessenger::DeclareMethodWithUnit() does not support a "
197           "method that has more than\n"           191           "method that has more than\n"
198        << "one arguments (or no argument). Ple    192        << "one arguments (or no argument). Please use "
199           "G4GenericMessenger::DeclareMethod m    193           "G4GenericMessenger::DeclareMethod method for\n"
200        << "your command <" << fullpath << ">."    194        << "your command <" << fullpath << ">.";
201     G4Exception("G4GenericMessenger::DeclareMe    195     G4Exception("G4GenericMessenger::DeclareMethodWithUnit()", "Intercom70002", FatalException, ed);
202   }                                               196   }
203   G4UIcommand* cmd = new G4UIcmdWithADoubleAnd    197   G4UIcommand* cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
204   (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd    198   (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetParameterName("value", false, false);
205   (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd    199   (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
206   if (!doc.empty()) {                             200   if (!doc.empty()) {
207     cmd->SetGuidance(doc);                        201     cmd->SetGuidance(doc);
208   }                                               202   }
209   return methods[name] = Method(fun, object, c    203   return methods[name] = Method(fun, object, cmd);
210 }                                                 204 }
211                                                   205 
212 G4String G4GenericMessenger::GetCurrentValue(G    206 G4String G4GenericMessenger::GetCurrentValue(G4UIcommand* command)
213 {                                                 207 {
214   if (properties.find(command->GetCommandName(    208   if (properties.find(command->GetCommandName()) != properties.cend()) {
215     Property& p = properties[command->GetComma    209     Property& p = properties[command->GetCommandName()];
216     return p.variable.ToString();                 210     return p.variable.ToString();
217   }                                               211   }
218   if (methods.find(command->GetCommandName())     212   if (methods.find(command->GetCommandName()) != methods.cend()) {
219     G4cout << " GetCurrentValue() is not avail    213     G4cout << " GetCurrentValue() is not available for a command defined by "
220               "G4GenericMessenger::DeclareMeth    214               "G4GenericMessenger::DeclareMethod()."
221            << G4endl;                             215            << G4endl;
222     return G4String();                            216     return G4String();
223   }                                               217   }
224                                                   218 
225   throw G4InvalidUICommand();                     219   throw G4InvalidUICommand();
226 }                                                 220 }
227                                                   221 
228 void G4GenericMessenger::SetNewValue(G4UIcomma    222 void G4GenericMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
229 {                                                 223 {
230   // Check if there are units on this commands    224   // Check if there are units on this commands
231   if (typeid(*command) == typeid(G4UIcmdWithAD    225   if (typeid(*command) == typeid(G4UIcmdWithADoubleAndUnit)) {
232     newValue = G4UIcommand::ConvertToString(G4    226     newValue = G4UIcommand::ConvertToString(G4UIcommand::ConvertToDimensionedDouble(newValue));
233   }                                               227   }
234   else if (typeid(*command) == typeid(G4UIcmdW    228   else if (typeid(*command) == typeid(G4UIcmdWith3VectorAndUnit)) {
235     newValue = G4UIcommand::ConvertToString(G4    229     newValue = G4UIcommand::ConvertToString(G4UIcommand::ConvertToDimensioned3Vector(newValue));
236   }                                               230   }
237   else if (typeid(*command) == typeid(G4UIcmdW << 
238     if(StoB(newValue)) {                       << 
239       newValue = "1";                          << 
240     } else {                                   << 
241       newValue = "0";                          << 
242     }                                          << 
243   }                                            << 
244                                                   231 
245   if (properties.find(command->GetCommandName(    232   if (properties.find(command->GetCommandName()) != properties.cend()) {
246     Property& p = properties[command->GetComma    233     Property& p = properties[command->GetCommandName()];
247     p.variable.FromString(newValue);              234     p.variable.FromString(newValue);
248   }                                               235   }
249   else if (methods.find(command->GetCommandNam    236   else if (methods.find(command->GetCommandName()) != methods.cend()) {
250     Method& m = methods[command->GetCommandNam    237     Method& m = methods[command->GetCommandName()];
251     if (m.method.NArg() == 0) {                   238     if (m.method.NArg() == 0) {
252       m.method.operator()(m.object);              239       m.method.operator()(m.object);
253     }                                             240     }
254     else if (m.method.NArg() > 0) {               241     else if (m.method.NArg() > 0) {
255       G4Tokenizer tokens(newValue);            << 242       m.method.operator()(m.object, newValue);
256       G4String paraValue;                      << 
257       for (std::size_t i = 0; i < m.method.NAr << 
258         G4String aToken = tokens();            << 
259         if(m.method.ArgType(i)==typeid(bool))  << 
260           if(StoB(aToken)) {                   << 
261             aToken = "1";                      << 
262           } else {                             << 
263             aToken = "0";                      << 
264           }                                    << 
265         }                                      << 
266         paraValue += aToken + " ";             << 
267       }                                        << 
268       m.method.operator()(m.object, paraValue) << 
269     }                                             243     }
270     else {                                        244     else {
271       throw G4InvalidUICommand();                 245       throw G4InvalidUICommand();
272     }                                             246     }
273   }                                               247   }
274 }                                                 248 }
275                                                   249 
276 void G4GenericMessenger::SetGuidance(const G4S    250 void G4GenericMessenger::SetGuidance(const G4String& s)
277 {                                                 251 {
278   dircmd->SetGuidance(s);                         252   dircmd->SetGuidance(s);
279 }                                                 253 }
280                                                   254 
281 G4GenericMessenger::Command& G4GenericMessenge    255 G4GenericMessenger::Command& G4GenericMessenger::Command::SetUnit(const G4String& unit,
282                                                   256                                                                   UnitSpec spec)
283 {                                                 257 {
284   // Change the type of command (unfortunatell    258   // Change the type of command (unfortunatelly this is done a posteriory)
285   // We need to delete the old command before     259   // We need to delete the old command before creating the new one and therefore
286   // we need to recover the information before    260   // we need to recover the information before the deletetion
287   if (G4Threading::IsMultithreadedApplication(    261   if (G4Threading::IsMultithreadedApplication()) {
288     G4String cmdpath = command->GetCommandPath    262     G4String cmdpath = command->GetCommandPath();
289     G4ExceptionDescription ed;                    263     G4ExceptionDescription ed;
290     ed << "G4GenericMessenger::Command::SetUni    264     ed << "G4GenericMessenger::Command::SetUnit() is thread-unsafe and should "
291           "not be used\n"                         265           "not be used\n"
292        << "in multi-threaded mode. For your co    266        << "in multi-threaded mode. For your command <" << cmdpath << ">, use\n"
293        << " DeclarePropertyWithUnit(const G4St    267        << " DeclarePropertyWithUnit(const G4String& name, const G4String& "
294           "defaultUnit,\n"                        268           "defaultUnit,\n"
295        << "                         const G4An    269        << "                         const G4AnyType& variable, const G4String& "
296           "doc)\n"                                270           "doc)\n"
297        << "or\n"                                  271        << "or\n"
298        << " DeclareMethodWithUnit(const G4Stri    272        << " DeclareMethodWithUnit(const G4String& name, const G4String& "
299           "defaultUnit,\n"                        273           "defaultUnit,\n"
300        << "                       const G4AnyT    274        << "                       const G4AnyType& variable, const G4String& "
301           "doc)\n"                                275           "doc)\n"
302        << "to define a command with a unit <"     276        << "to define a command with a unit <" << unit << ">.";
303     if (spec != UnitDefault) {                    277     if (spec != UnitDefault) {
304       ed << "\nPlease use a default unit inste    278       ed << "\nPlease use a default unit instead of unit category.";
305     }                                             279     }
306     G4Exception("G4GenericMessenger::Command::    280     G4Exception("G4GenericMessenger::Command::SetUnit()", "Intercom70001", FatalException, ed);
307     return *this;                                 281     return *this;
308   }                                               282   }
309                                                   283 
310   G4String cmdpath = command->GetCommandPath()    284   G4String cmdpath = command->GetCommandPath();
311   G4UImessenger* messenger = command->GetMesse    285   G4UImessenger* messenger = command->GetMessenger();
312   G4String range = command->GetRange();           286   G4String range = command->GetRange();
313   std::vector<G4String> guidance;                 287   std::vector<G4String> guidance;
314   G4String par_name = command->GetParameter(0)    288   G4String par_name = command->GetParameter(0)->GetParameterName();
315   G4bool par_omitable = command->GetParameter(    289   G4bool par_omitable = command->GetParameter(0)->IsOmittable();
316   for (G4int i = 0; i < (G4int)command->GetGui    290   for (G4int i = 0; i < (G4int)command->GetGuidanceEntries(); ++i) {
317     guidance.push_back(command->GetGuidanceLin    291     guidance.push_back(command->GetGuidanceLine(i));
318   }                                               292   }
319   // Before deleting the command we need to ad    293   // Before deleting the command we need to add a fake one to avoid deleting
320   // the directory entry and with its guidance    294   // the directory entry and with its guidance
321   G4UIcommand tmp((cmdpath + "_tmp").c_str(),     295   G4UIcommand tmp((cmdpath + "_tmp").c_str(), messenger);
322   delete command;                                 296   delete command;
323                                                   297 
324   if (*type == typeid(float) || *type == typei    298   if (*type == typeid(float) || *type == typeid(double)) {
325     auto* cmd_t = new G4UIcmdWithADoubleAndUni    299     auto* cmd_t = new G4UIcmdWithADoubleAndUnit(cmdpath, messenger);
326     if (spec == UnitDefault) {                    300     if (spec == UnitDefault) {
327       cmd_t->SetDefaultUnit(unit);                301       cmd_t->SetDefaultUnit(unit);
328     }                                             302     }
329     else if (spec == UnitCategory) {              303     else if (spec == UnitCategory) {
330       cmd_t->SetUnitCategory(unit);               304       cmd_t->SetUnitCategory(unit);
331     }                                             305     }
332     cmd_t->SetParameterName(par_name, par_omit    306     cmd_t->SetParameterName(par_name, par_omitable);
333     command = cmd_t;                              307     command = cmd_t;
334   }                                               308   }
335   else if (*type == typeid(G4ThreeVector)) {      309   else if (*type == typeid(G4ThreeVector)) {
336     auto* cmd_t = new G4UIcmdWith3VectorAndUni    310     auto* cmd_t = new G4UIcmdWith3VectorAndUnit(cmdpath, messenger);
337     if (spec == UnitDefault) {                    311     if (spec == UnitDefault) {
338       cmd_t->SetDefaultUnit(unit);                312       cmd_t->SetDefaultUnit(unit);
339     }                                             313     }
340     else if (spec == UnitCategory) {              314     else if (spec == UnitCategory) {
341       cmd_t->SetUnitCategory(unit);               315       cmd_t->SetUnitCategory(unit);
342     }                                             316     }
343     command = cmd_t;                              317     command = cmd_t;
344   }                                               318   }
345   else {                                          319   else {
346     G4cerr << "Only parameters of type <double    320     G4cerr << "Only parameters of type <double> or <float> can be associated "
347               "with units"                        321               "with units"
348            << G4endl;                             322            << G4endl;
349     return *this;                                 323     return *this;
350   }                                               324   }
351   for (auto& i : guidance) {                      325   for (auto& i : guidance) {
352     command->SetGuidance(i);                      326     command->SetGuidance(i);
353   }                                               327   }
354   command->SetRange(range);                       328   command->SetRange(range);
355   return *this;                                   329   return *this;
356 }                                                 330 }
357                                                   331 
358 G4GenericMessenger::Command& G4GenericMessenge    332 G4GenericMessenger::Command& G4GenericMessenger::Command::SetParameterName(const G4String& name,
359                                                   333                                                                            G4bool omittable,
360                                                   334                                                                            G4bool currentAsDefault)
361 {                                                 335 {
362   return SetParameterName(0, name, omittable,     336   return SetParameterName(0, name, omittable, currentAsDefault);
363 }                                                 337 }
364                                                   338 
365 G4GenericMessenger::Command& G4GenericMessenge    339 G4GenericMessenger::Command& G4GenericMessenger::Command::SetParameterName(G4int pIdx,
366                                                   340                                                                            const G4String& name,
367                                                   341                                                                            G4bool omittable,
368                                                   342                                                                            G4bool currentAsDefault)
369 {                                                 343 {
370   if (pIdx < 0 || pIdx >= (G4int)(command->Get    344   if (pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries())) {
371     G4cerr << "Invalid parameter index : " <<     345     G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored." << G4endl;
372     return *this;                                 346     return *this;
373   }                                               347   }
374   G4UIparameter* theParam = command->GetParame    348   G4UIparameter* theParam = command->GetParameter(pIdx);
375   theParam->SetParameterName(name);               349   theParam->SetParameterName(name);
376   theParam->SetOmittable(omittable);              350   theParam->SetOmittable(omittable);
377   theParam->SetCurrentAsDefault(currentAsDefau    351   theParam->SetCurrentAsDefault(currentAsDefault);
378   return *this;                                   352   return *this;
379 }                                                 353 }
380                                                   354 
381 G4GenericMessenger::Command& G4GenericMessenge    355 G4GenericMessenger::Command& G4GenericMessenger::Command::SetParameterName(const G4String& namex,
382                                                   356                                                                            const G4String& namey,
383                                                   357                                                                            const G4String& namez,
384                                                   358                                                                            G4bool omittable,
385                                                   359                                                                            G4bool currentAsDefault)
386 {                                                 360 {
387   if (*type != typeid(G4ThreeVector)) {           361   if (*type != typeid(G4ThreeVector)) {
388     G4cerr << "This SetParameterName method is    362     G4cerr << "This SetParameterName method is for G4ThreeVector!! "
389            << "Method ignored." << G4endl;        363            << "Method ignored." << G4endl;
390     return *this;                                 364     return *this;
391   }                                               365   }
392   G4UIparameter* theParam = command->GetParame    366   G4UIparameter* theParam = command->GetParameter(0);
393   theParam->SetParameterName(namex);              367   theParam->SetParameterName(namex);
394   theParam->SetOmittable(omittable);              368   theParam->SetOmittable(omittable);
395   theParam->SetCurrentAsDefault(currentAsDefau    369   theParam->SetCurrentAsDefault(currentAsDefault);
396   theParam = command->GetParameter(1);            370   theParam = command->GetParameter(1);
397   theParam->SetParameterName(namey);              371   theParam->SetParameterName(namey);
398   theParam->SetOmittable(omittable);              372   theParam->SetOmittable(omittable);
399   theParam->SetCurrentAsDefault(currentAsDefau    373   theParam->SetCurrentAsDefault(currentAsDefault);
400   theParam = command->GetParameter(2);            374   theParam = command->GetParameter(2);
401   theParam->SetParameterName(namez);              375   theParam->SetParameterName(namez);
402   theParam->SetOmittable(omittable);              376   theParam->SetOmittable(omittable);
403   theParam->SetCurrentAsDefault(currentAsDefau    377   theParam->SetCurrentAsDefault(currentAsDefault);
404   return *this;                                   378   return *this;
405 }                                                 379 }
406                                                   380 
407 G4GenericMessenger::Command& G4GenericMessenge    381 G4GenericMessenger::Command& G4GenericMessenger::Command::SetCandidates(const G4String& candList)
408 {                                                 382 {
409   return SetCandidates(0, candList);              383   return SetCandidates(0, candList);
410 }                                                 384 }
411                                                   385 
412 G4GenericMessenger::Command& G4GenericMessenge    386 G4GenericMessenger::Command& G4GenericMessenger::Command::SetCandidates(G4int pIdx,
413                                                   387                                                                         const G4String& candList)
414 {                                                 388 {
415   if (pIdx < 0 || pIdx >= (G4int)(command->Get    389   if (pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries())) {
416     G4cerr << "Invalid parameter index : " <<     390     G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored." << G4endl;
417     return *this;                                 391     return *this;
418   }                                               392   }
419   G4UIparameter* theParam = command->GetParame    393   G4UIparameter* theParam = command->GetParameter(pIdx);
420   theParam->SetParameterCandidates(candList);     394   theParam->SetParameterCandidates(candList);
421   return *this;                                   395   return *this;
422 }                                                 396 }
423                                                   397 
424 G4GenericMessenger::Command& G4GenericMessenge    398 G4GenericMessenger::Command& G4GenericMessenger::Command::SetDefaultValue(const G4String& defVal)
425 {                                                 399 {
426   return SetDefaultValue(0, defVal);              400   return SetDefaultValue(0, defVal);
427 }                                                 401 }
428                                                   402 
429 G4GenericMessenger::Command& G4GenericMessenge    403 G4GenericMessenger::Command& G4GenericMessenger::Command::SetDefaultValue(G4int pIdx,
430                                                   404                                                                           const G4String& defVal)
431 {                                                 405 {
432   if (pIdx < 0 || pIdx >= (G4int)(command->Get    406   if (pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries())) {
433     G4cerr << "Invalid parameter index : " <<     407     G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored." << G4endl;
434     return *this;                                 408     return *this;
435   }                                               409   }
436   G4UIparameter* theParam = command->GetParame    410   G4UIparameter* theParam = command->GetParameter(pIdx);
437   theParam->SetDefaultValue(defVal);              411   theParam->SetDefaultValue(defVal);
438   return *this;                                   412   return *this;
439 }                                                 413 }
440                                                   414