Reputation: 1568
I'm trying to build a simple command processor in C++ and I'm stuck on a not so easy issue. I have a class (CommandProcessor) that takes a request of some form. This request is transformed into an object (Command) and put onto a queue or started immediately if there is no running command. The Command object is responsible for fullfilling the request. When it's completed, the CommandProcessor is notified so it can starts processing another command. This callback is where my problem lies : the CommandProcessor should delete the Command at this point, however, since the CommandProcessor is notified during the execution of a method in the Command object, the Command object ends up indirectly deleting itself.
I could possibly delay the callback at the end of the method to ensure that nothing gets executed after it, but I feel that this is a bit of a brittle design.
My other solution was to keep a reference to the completed command and delete it when a new request enters the CommandProcessor, but there's 2 problems with that, the first being that I'm basically using memory that may never be deleted and the second is that the Command object contains some resources that needs to be released as soon as possible (e.g.file handler).
I'm probably not the first guy to stumble on this problem so I was wondering if anybody had a better idea.
Clarifications To simplify, we can say that my program is singlethreaded, that is, the CommandProcessor and the Command object are executed on the same thread. However, not much is executed in the command object aside from doing a bunch of async system calls and waiting for the callbacks. In other words, the Command object's Execute method is non-blocking. Also, only one command is executing at a time.
Note also that this is a very "managed" design, i.e. something that would work in a language like C#, since the garbage collector would be responsible for deleting the Command object later in the lifetime of the program.
Thanks!
Upvotes: 2
Views: 155
Reputation: 4763
From my understanding of the initial post, you have the following stack (due to single threading) :
CommandProcessor->StartCommand(Command1)->..async.. ->Command1.onComplete()->CommandProcessor->StartCommand(command2)-> command1 gets deleted
You would want to prevent Command1 to delete itself , preferably by doing :
CommandProcessor->deleteFinishedCommand
One way to approach this in single threaded implementations is to have keep a pointer to the previously finished commands and call a finishCommand prior to startCommand.
void finishCommand(Command *aCommand)
{
if (previouslyFinished!=NULL)
{
delete previouslyFinished;
}
previouslyFinished=aCommand;
}
The downfall is that this will delay command deletion with 1 command , so you will basically always have a command in the memory.
The most important part here is that Command.OnComplete() needs to close ALL handles from the command.
This isn't very elegant, but it will help avoid your Command deleting itself.
Further improvements would allow you to delete the previously finished command earlyer (like a watcher thread).
Upvotes: 1