Skip to content

refactor: reduce the use of cvm::main()#924

Closed
HanatoK wants to merge 8 commits intoColvars:masterfrom
HanatoK:fix_cudagm_build
Closed

refactor: reduce the use of cvm::main()#924
HanatoK wants to merge 8 commits intoColvars:masterfrom
HanatoK:fix_cudagm_build

Conversation

@HanatoK
Copy link
Copy Markdown
Member

@HanatoK HanatoK commented Mar 24, 2026

This PR is intended to partially complete #886.

@HanatoK HanatoK requested review from giacomofiorin and jhenin March 24, 2026 21:50
Comment thread src/colvar.cpp Outdated
global_cvc_map[def_config_key] = []() {
return new def_class_name();
global_cvc_map[def_config_key] = [&]() {
return new def_class_name(cvmodule);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to avoid this? We can pass the pointer using a base-class method immediately after creating the object

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how to avoid it. Could you give more hints?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that would mean using a cvc constructor that sets cvmodule to nullptr, and then using deferred initialization. But that seems riskier to me. Right now I'm not sure everything is robust to cvmodule being null.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, I have changed the code to avoid capturing the reference of this pointer in d16ae99, since the previous code crashed in VMD.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that would mean using a cvc constructor that sets cvmodule to nullptr, and then using deferred initialization. But that seems riskier to me. Right now I'm not sure everything is robust to cvmodule being null.

As hinted in the other comment, yes, I'm thinking about deferring initialization for everything that involves data outside the scope of the object being constructed.

If we were to move all calls to the colvardeps functions to the init() function, what would break?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think moving the pointer initialization to init() is a good idea. The colvarmodule* pointer should be available at construction, to at least facilitate debugging with cvmodule->log.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds fine, but for initializing POD members, which is what a constructor should really do, do we need to debug?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly speaking, I am not sure. colvardeps does not have an init() function, and if I understand correctly what @jhenin was trying to do, the empty constructor colvardeps() is intended to be deprecated, so other classes derived from colvardeps should have colvarmodule* cvmodule_in as a parameter in the constructors.

I have completed most of the refactoring following the same pattern in #886 for derived classes of colvardeps in later commits (see 727952b). The C and fortran interfaces should work as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we don't need to have an init() function for colvardeps, the one for the class directly derived from it is the one that matters: in this case, colvar::cvc::init().

It's very likely that an Abstract Syntax Tree would require deferred initialization, so I personally would rather work toward that. Am I missing something here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I admit that whether using deferred initialization or not is a choice of design. I feel that using colvarmodule* cvmodule_in in the constructors is more robust, and it follows the same pattern in #886 .

The AST should be OK because the tree of colvardeps already uses the pointers:

std::vector<colvardeps *> children;
std::vector<colvardeps *> parents;

Comment thread src/colvarcomp.cpp

// This constructor depends on a static cvm pointer and is deprecated
colvar::cvc::cvc()
: colvardeps(cvm::main())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @jhenin may have already thought about improving colvardeps so that it doesn't need this pointer.

Copy link
Copy Markdown
Member

@jhenin jhenin Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, it's not that colvardeps itself definitely needs the pointer, but rather, colvardeps is used as a vehicle to share the pointer with many classes that inherit from it. If that was to be removed, the pointer would have to be added separately to the cvc, colvar, and colvarbias classes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we'd have the same issue, that all cvc constructors would need the pointer

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source of the problem is that currently in these constructors we're doing stuff that goes outside the object being constructed. We should rather do that in init(), and that point we would have a valid cvmodule pointer.

Comment thread src/colvarscript_commands.h Outdated
// Utility functions used to query the command database
extern "C" {

class colvarscript;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I need to remove this forward declaration in extern "C" and use an opaque pointer to colvarproxy in the functions below.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I have changed the C interface functions to use void* proxy_in.

From the C interface, it is impossible to use the colvarscript class or
even get a pointer to the colvarscript object. The example C code in
C_test.c shows that only an opaque pointer to colvarproxy is available,
so the C functions in extern "C" should get the script object from the
opaque pointer instead of expecting the script object being passed as a
function argument.
@HanatoK
Copy link
Copy Markdown
Member Author

HanatoK commented Mar 27, 2026

Superseded by #925.

@HanatoK HanatoK closed this Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants