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
Switch the consensus algorithms interface to using function objects. #13272
Conversation
55d6929
to
9722d91
Compare
consensus_algo.reset(new NBX<T1, T2>(process, comm)); | ||
consensus_algo.reset(new NBX<T1, T2>()); | ||
else | ||
# endif | ||
#endif | ||
if (n_procs > 1) | ||
consensus_algo.reset(new PEX<T1, T2>(process, comm)); | ||
consensus_algo.reset(new PEX<T1, T2>()); | ||
else | ||
consensus_algo.reset(new Serial<T1, T2>(process, comm)); | ||
} | ||
|
||
|
||
consensus_algo.reset(new Serial<T1, T2>()); |
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.
In a side-by-side, you would see that this resetting of the member variable happened in the constructor. I had to move this into the run()
function because we now have two constructors, only one of which knows how to choose the algorithm. That also means that the consensus_algorithm
variable is actually only used in this one run()
function any more. I could move it from a member variable to a local variable. I'll do so in a follow-up patch, but thought I'd try to keep things minimal for this PR.
9ea0865
to
b3b7487
Compare
Assert((Utilities::MPI::job_supports_mpi() == false) || | ||
(Utilities::MPI::n_mpi_processes(comm) == 1), | ||
ExcMessage("You shouldn't use the 'Serial' class on " | ||
"communicators that have more than one process " | ||
"associated with it.")); |
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 strictly speaking an unrelated addition, but I thought it was a good idea while I was already working on this function.
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.
Looks overall good.
But to be honest, I am not that fond of that additional parameters need to be passed to the internal functions and it does not help the reading (the NBX algorithms used to be 7 locs). The logical next step would be to move all internal variables into the run function and at that time one could make the function static and probably one would not even need a class but only a free function. The helper functions would have even longer argument lists...
Yes, it is not crazy to suggest that a free function would have been the way to go. To me as a software designer, here is the difference in variables:
This is the separation I have chosen in this patch: I pass the inputs around as function arguments, and describe the state of the object via member variables. I think I did that consistently. Now, oftentimes, member variables would describe and keep the state of the object between one function call and the next. Here, this is not the case: At the end of the (By way of already arguing the opposite direction: One could of course say that the operations that are encoded in the All this to say that I don't think the current design of these classes is bad; I just wanted to provide a software-design-theoretic explanation for why the patch is written this way :-) |
Maybe to bring this into one sentence:
|
b3b7487
to
db6adac
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.
I think this is a reasonable step. I am not particularly happy with the increasing number of function arguments, given that the state is not passed along between the member functions. Also, I generally prefer functions with a named signature (like member functions rather than lambdas) as they are much easier to track down when you are in some lower-level tool as I keep using them, but it seems a problem not shared by many others. On the other hand, I feel that being able to eventually call ConsensusAlgorithms::nbx(...)
would be great.
I commit to making |
@peterrum any final comments here? I think we should go on with this topic now. |
This is a proposal to fix #13208. The idea is to switch the CA
run()
function to function objects instead of theProcess
object. I've managed to keep the existing functions around, and the patch currently does not convert any of the existing CA users. In other words, things are backward compatible. I will change the users to the new interface in a later patch or commit.Here is what I was setting out for:
run()
function that simply doesn't takeanswer_request()
andprocess_answer()
(renamed fromread_answer()
) functions.AnonymousProcess
class unnecessary: Instead of storing the lambda functions inAnonymousProcess
, one can just pass them torun()
directly. This is what I would have liked to do inFETools::extrapolate()
, for example.Process
class -- I keep aInterface::run()
function that simply unpacks theProcess
object and calls the one that takes function objects.and put their output into the last function argument. But in all cases, these output buffers are not reused, and so there is no good reason to not just write the function as
where the object is simply returned. In times of move constructors, this should not have any adverse effect, but is more "functional" and easier to read. In some cases, it also avoids having to use named variables.
Overall, this patch should have no actual functional difference, and it should be backward compatible.
Thoughts about the approach?
/rebuild