我正在尝试用C ++构建一个简单的命令处理器,而我却陷入了一个不那么容易的问题。我有一个类(CommandProcessor)接受某种形式的请求。如果没有运行命令,此请求将转换为对象(Command)并放入队列或立即启动。 Command对象负责完成请求。完成后,会通知CommandProcessor,以便它可以开始处理另一个命令。这个回调是我的问题所在:CommandProcessor此时应删除Command,但是,由于CommandProcessor在Command对象中执行方法期间得到通知,因此Command对象最终会间接删除自身。
我可能会在方法结束时延迟回调,以确保在它之后没有执行任何操作,但我觉得这有点脆弱的设计。
我的另一个解决方案是保留对已完成命令的引用并在新请求进入CommandProcessor时删除它,但是有两个问题,第一个是我基本上使用的内存可能永远不会被删除第二,Command对象包含一些需要尽快释放的资源(例如文件处理程序)。
我可能不是第一个偶然发现这个问题的人,所以我想知道是否有人有更好的想法。
澄清 为了简化,我们可以说我的程序是单线程的,即CommandProcessor和Command对象在同一个线程上执行。但是,除了执行一堆异步系统调用并等待回调之外,在命令对象中执行的操作并不多。换句话说,Command对象的Execute方法是非阻塞的。此外,一次只执行一个命令。
另请注意,这是一种非常“受管理”的设计,即可以使用C#等语言的设计,因为垃圾收集器将负责在程序的生命周期中删除Command对象。
谢谢!
答案 0 :(得分:1)
根据我对初始帖子的理解,你有以下堆栈(由于单线程):
CommandProcessor-> StartCommand(Command1) - > .. async .. - > Command1.onComplete() - > CommandProcessor-> StartCommand(command2) - > command1被删除
您可能希望阻止Command1自行删除,最好是执行以下操作:
CommandProcessor-> deleteFinishedCommand
在单线程实现中处理此问题的一种方法是保留指向先前完成的命令的指针,并在startCommand之前调用finishCommand。
void finishCommand(Command *aCommand)
{
if (previouslyFinished!=NULL)
{
delete previouslyFinished;
}
previouslyFinished=aCommand;
}
失败的原因是这会使用1命令延迟删除命令,所以你基本上总是在内存中有一个命令。
这里最重要的部分是Command.OnComplete()需要从命令中关闭所有句柄。
这不是很优雅,但它有助于避免命令自行删除。
进一步的改进将允许您尽早删除先前完成的命令(如观察者线程)。