簡體   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