-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Several improvements to colvar component classes #643
Conversation
43da335
to
b705999
Compare
b705999
to
be5a4b8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the original constructor code with cvm::error
return as early as possible, because continue to execute the code following cvm::error
will result in a crash. When moving to an init
function this behavior should keep the same. Otherwise VMD users may experience crashes after loading the wrong data into some of the CVs, for example, a pathFile
with the wrong format for gpathCV
.
src/colvarcomp_gpath.cpp
Outdated
@@ -317,13 +353,13 @@ colvar::gzpath::gzpath(std::string const &conf): CartesianBasedPath(conf) { | |||
cvm::log(std::string("Geometric path z(σ) will use the square of distance from current frame to path compute z\n")); | |||
} | |||
if (total_reference_frames < 2) { | |||
cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gzpath requires at least 2 frames.\n"); | |||
return; | |||
error_code |= cvm::error("Error: you have specified " + cvm::to_str(total_reference_frames) + " reference frames, but gzpath requires at least 2 frames.\n", COLVARS_INPUT_ERROR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the return statement moved to the end of the function? I am a bit worried that if it doesn't return here, the following code would segfault or crash, which is OK for NAMD but not a good user experience for VMD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok with me to return early, I just overlooked the possibility of a crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the instances that you pointed out into an early return with error.
|
||
int colvar::gspath::init(std::string const &conf) | ||
{ | ||
int error_code = CartesianBasedPath::init(conf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need to check the error code and return early too? If you think it is too complicated to return error code in derived classes, we can throw exceptions and catch them in some of the upper level functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dude, are you really advocating for supporting VMD and and propose adding exceptions in the same review round? ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should be clearer. Exception is just one of the solutions, and if I were you I might use exceptions in any init
functions and catch them in colvar::update_cvc_config
. Early return is another one, which may need more lines of code for both base and derived classes. Using either of them should be enough. As for VMD, it is just an example of interactive applications. Colvars as a library should not terminate the main interactive program if there is an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should be clearer, too :-) Exceptions would be convenient on their own, actually. We haven't used them in the past mostly to play it safe with VMD, which traditionally aims to support exotic and/or ancient compilers. Although compiler support has become more uniform with C++11, best practices like the Google Style Guide don't encourage vendors to support them well.
I think that adding early returns wherever it looks like the code may crash is probably the safest right now. I think that's still a minority of all error conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a common pattern in several places, I made similar "early return" changes in #650 and Haochuan added a bunch more in this PR.
I wouldn't mind having this in more places, that is, everywhere, and I wonder if there is a more concise / elegant / modern / systematic way of formulating this, besides exceptions. The C programmer in me would make it a macro... There, I said it, I'm old. C++11 best practices and Google Style Guide: get off my lawn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be clear, I'm old too but I would be happy to embrace anything that the maintainers of a major package (whatever their age might be) will commit to approve.
In writing, please.
1e29e66
to
f8a8b6c
Compare
Also remove the preprocessor macro defining member functions, in favor of using C++ inheritance throughout. Therefore, the decrease in the amount of duplicated code is much higher than how it appears from the diff.
In that code version, distanceVec was not yet honoring forceNoPBC
Return the error code earlier to prevent crashes in interactive programs.
0a6b87f
to
3957f1e
Compare
@HanatoK Thanks for revising the PCV constructors! |
|
||
int colvar::gspath::init(std::string const &conf) | ||
{ | ||
int error_code = CartesianBasedPath::init(conf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a common pattern in several places, I made similar "early return" changes in #650 and Haochuan added a bunch more in this PR.
I wouldn't mind having this in more places, that is, everywhere, and I wonder if there is a more concise / elegant / modern / systematic way of formulating this, besides exceptions. The C programmer in me would make it a macro... There, I said it, I'm old. C++11 best practices and Google Style Guide: get off my lawn.
[update-doc]
silence uninitialized access valgrind warning lammps/lammps@c3cc497
This PR contains several improvements to
colvar::cvc
and its derived classes, including substantial simplification of the code and some fixes where the previous implementation was incorrect (distanceVec
metrics) or less robust (period
).init(conf)
now initializes an object from the configuration string, by modifying existing defaults.distanceVec
metric functions are now consistent with the documentation.period
can now be set only for those CVCs that allow it: that includesdistanceZ
as well all periodic angles (only where someone needs something else than 360°).std::shared_ptr
is now used to collect the CVC objects inside the colvar level. I have not yet touched the arrays of CVC pointers inside complex CVC objects (e.g. the protein CVCs or the combination ones) because those will be modified anyway in upcoming work.Other possible improvements that were out of scope to do:
init()
function, it would be theoretically possible to call that fromcolvar::update_cvc_config()
, i.e. the backend for themodifycvcs
scripting command. Currently, the base class methodcvc::init()
is still called, because not all the derived ones are idempotent yet.colvarcomp.h
could be split up to reduce interdependencies.