在遍历处理程序的向量时注册和注销处理程序

Register and unregister a handler while iterating throught the vector of handlers

本文关键字:程序 处理 注册 注销 遍历 向量      更新时间:2023-10-16

我有一个非常小的程序,它启动一个线程并将事件分派到已注册的处理程序集。Handlers类如下所示。

class Handler
{
public:
/* OnEvent must return void. This is part of the user interface agreement */
virtual void OnEvent(struct Event*) = 0;
virtual ~Handler();
};

处理程序保存在矢量内

std::vector<Handler*> handlers;

我可以使用register函数向向量添加一个处理程序并使用unregister函数从向量中删除处理程序。处理人员可以可以在OnEvent函数中添加或删除。

原型低于

void registerHandler(Handler *h);
void unregisterHandler(Handler *h);

线程函数如下所示。它将阻塞事件,一旦接收到事件,它将把这个事件分派给向量中的每个处理程序

void thread_function()
{
struct Event* e = getEvent();

/* Function will receive an event and will invoke handlers one by one */
for(auto s = 0; s < handlers.size(); ++s)
{
/* Register and unregister function can be called inside OnEvent. */
handlers[s]->OnEvent();
}
}

在OnEvent函数内部的向量中添加和删除处理程序的最佳方式是什么?

我的想法是。当在OnEvent内部调用register时,我将把一个处理程序推回到处理程序列表中。但我想不出如何从向量中删除处理程序。如果我从向量中删除一个处理程序,迭代器将不再有效。听到你们的想法会很有趣的,伙计们。

谢谢

如果处理程序更改仅在事件处理后生效,则可以复制处理程序数组:

std::vector<Handler*> handlers;
void thread_function(){
struct Event* e = getEvent();
std::vector<Handler*> handlersCopy = handlers;
for(Handler* h : handlersCopy) {
h->OnEvent();
}
}

如果你想阻止处理在处理过程中被删除的处理程序,你可以这样做:

std::vector<Handler*> handlers;
bool isDispatching = false;
std::unordered_set<Handler*> disabledHandlers;
void unregisterHandler(Handler *h){
handlers.erase(handlers.find(h));
if (isDispatching){
disabledHandlers.insert(h);
}
}
void thread_function(){
struct Event* e = getEvent();
isDispatching = true;
std::vector<Handler*> handlersCopy = handlers;
for(Handler* h : handlersCopy) {
if(disabledHandlers.find(h) != disabledHandlers.end()){
continue;
}
h->OnEvent();
}
isDispatching = false;
disabledHandlers.clear();
}