繁体   English   中英

使用 std::shared_ptr/weak_ptr 的简化观察者模式

[英]simplfied observer pattern with std::shared_ptr/weak_ptr

这是一个简化的观察者模式:

  1. 一位创建者在启动时创建配置文件,并在完成时“销毁”它。
  2. 零,一个或多个观察者随时尝试“查看”配置文件。

要实现它,诀窍是观察者应该 refcnt 配置文件,因此最后一个观察者(或创建者)可以安全地销毁它。

我可以在没有 shared_ptr/weak_ptr 的情况下做到这一点,但我想知道使用它们是否可以避免重新发明轮子。

这是我的代码:

#include <iostream>
#include <memory>
#include <thread>
#include <cassert>

volatile bool playing = true;

class Profile {
public:
    int a_;
    Profile(int v) {a_ = v;}
};

std::shared_ptr<Profile> g_profile{ nullptr };

void observer() {
    do {
        // observe profile if I can
        std::weak_ptr<Profile> weak = g_profile;
        if (auto prof = weak.lock()) {
            auto a = prof->a_;
            // if prof is stable, I shall see the same a_
            assert(a == prof->a_);
        }
        else {
            std::cout << ".";
        }
    } while (playing);
}

void creator() {
    do {
        // create profile when I start
        g_profile.reset(new Profile(std::rand()));
        std::weak_ptr<Profile> weak = g_profile;
        assert(weak.lock() != nullptr);
        
        // doing some work ...

        // destroy profile when I am done
        g_profile.reset();
    } while (playing);
}

void timer() {
    std::this_thread::sleep_for(std::chrono::seconds(10));
    playing = false;
}

int main() {
    std::thread cr{ creator };
    std::thread ob{ observer };
    std::thread tm{ timer };
    cr.join();ob.join();tm.join();

    // no memory leak
}

但是程序在std::weak_ptr<Profile> weak = g_profileassert(a == prof->a_)处崩溃。 所以这是我的问题:

  1. 你有一个指针用shared_ptr/weak_ptr实现观察者模式(或变体)吗?
  2. 上面的代码有什么问题? 你能做对吗?

当一个线程从共享指针g_profile (观察者)读取而另一个线程写入它时(当创建者调用std::shared_ptr::reset时),您有未定义的行为

如果要从两个线程中使用shared_ptr ,则必须使用 lock 或atomic_shared_ptr

volatile也不像在 java 中那样保证任何同步。 看到这个答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM