c++ - 在构造函数中注册 weak_ptr 观察者

标签 c++ multithreading listener shared-ptr observer-pattern

我正在尝试重写我们的 Observer/Observable 实现以使用 std::shared_ptr/std::weak_ptr 来摆脱代码中当前存在的一些讨厌的竞争条件。

通常,观察者会在满足某些条件时或在构造子对象时注册自己,如下所示:

// Used to be raw 'this' now child instead derives a weak_ptr and stores it
child->addObserver(shared_from_this()) 

然后像这样在析构函数中注销自己:

child->removeObserver(this); // Not shared_from_this() since in destructor

在某些情况下这工作正常,但在许多情况下,观察者希望在构造函数中注册自己。由于 shared_ptr 尚未创建,我们无法调用 shared_from_this()。

由于 weak_ptr 通常被推荐用于在 C++ 中实现观察者模式,我想知道解决上述问题的惯用方法是什么。

一些想法:

  • 让创建观察者对象的工厂注册观察者。这从观察者那里泄漏了抽象(为什么工厂应该知道 child 想要观察谁?)并迫使观察者暴露它可能想要观察的内部对象
  • 添加一个在构造函数完成后由工厂调用的 init 方法,比上面的要好,但是构造函数和 init 之间的语义区别是什么?应该在哪里做什么?它甚至是RAII吗?事实上,有些语言甚至将它们的构造函数称为 init。
  • 将一个 lambda 传递给构造函数,该构造函数采用另一个在构造后调用的 lambda
  • 也许是模板魔法?
  • 以其他方式实现观察者模式。

最佳答案

处理您所问问题的一种方法是创建一个由 shared_ptr 持有并包含在“parent”中的显式观察者对象实例。观察者对象会将观察结果发送给父对象。

但是,由于子进程正在将 shared_ptr 注册到 weak_ptr,实际上父进程没有必要显式地移除自己作为观察者的身份。当 child 向观察者发送通知时,它首先检查 weak_ptr 是否有效。如果不再有效,它可以就地移除观察者而不是通知。

void notify_observers (Event e) const {
    auto o = observers_.begin();
    auto erase = [this](decltype(o) o) {
        return observers_.erase(o);
    };
    while (o != observers_.end()) {
        if (auto l = o->lock()) ++o, l->notify(e);
        else o = locked_call(erase, o);
    }
}

Try it online!

关于c++ - 在构造函数中注册 weak_ptr 观察者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53727439/

相关文章:

c++ - 指向共享对象的指针数组

c++ - 是否有一对正宽度和长度值会返回负面积?

c++ - getline c++ 没有匹配函数

c++ - OpenCV 中聚类方法的并行化

android-一个按钮中的多onClick监听器

java - 使用 listener 和 DoubleProperty 获取变化量

c++ - 用于在运行时记录调用堆栈的库 (Windows/Linux)

c# - 使用 C# 和 APM 时 CPU 使用率不会达到 100% 的原因是什么?

c# - 在另一个线程中创建 WPF 命令

jboss - 在 Keycloak 中配置事件监听器