オブザーバーパターンSubject
から安全なクラスを書き込もうとしています。次のような方法でインスタンスを保存するのに、を使用するのが最善の方法であるかどうかを知りたいです。weak_ptr
IObserver
IObserver
解放されたインスタンスを使用することはできません。Subject
クラスは、解放されるべき参照を保持しません(IObserver
リスナーの失効の問題)。- クラスは
Subject
スレッドセーフである必要があります。
残念ながら、私たちのコーディング標準では、ブーストの使用は許可されていません。私は前世で悪い人だったと思います。幸い、C ++ 11(Visual Studio 2012に付属しているもの)を使用できます。
これがサンプルObserver
クラスです。
// Observer interface that supports notify() method
class IObserver
{
public:
virtual void notify() const = 0;
virtual ~IObserver() {}
};
// Concrete observer implementation that prints a message
class Observer : public IObserver
{
public:
Observer( const std::string& message) : m_message( message ){}
void notify() const {
printf( "%s\r\n", m_message.c_str() );
}
private:
std::string m_message;
};
そして、これがSubject
クラスです。
// Subject which registers observers and notifies them as needed.
class Subject
{
public:
// Use shared_ptr to guarantee the observer is valid right now
void registerObserver( const std::shared_ptr<IObserver>& o )
{
std::lock_guard<std::mutex> guard( m_observersMutex );
m_observers.push_back( o );
}
void unregisterObserver( const std::shared_ptr<IObserver>& o )
{
std::lock_guard<std::mutex> guard( m_observersMutex );
// Code to remove the observer from m_observersMutex
}
// This is a method that is run in its own thread that notifies observers of some event
void doNotify()
{
std::lock_guard<std::mutex> guard( m_observersMutex );
// Notify any valid observers of events.
std::for_each( m_observers.cbegin(), m_observers.cend(),
[]( const std::weak_ptr<IObserver>& o )
{
auto observer = o.lock();
if ( observer ) {
observer->notify();
}
} );
// Remove any dead observers. These are ones which have expired().
m_observers.erase( std::remove_if( m_observers.begin(), m_observers.end(),
[]( const std::weak_ptr<IObserver>& o )
{
return o.expired();
} ), m_observers.end() );
}
private:
std::vector<std::weak_ptr<IObserver>> m_observers;
std::mutex m_observersMutex;
};
演習するコードは次のSubject
とおりです。
int main(int argc, wchar_t* argv[])
{
Subject subject;
auto observerHello = std::make_shared<Observer>( "Hello world" );
subject.registerObserver( observerHello );
{
// Create a scope to show unregistration.
auto observerBye = std::make_shared<Observer>( "Good bye" );
subject.registerObserver( observerBye );
subject.doNotify();
}
printf( "%s\r\n", "Observer good bye is now be destructed" );
subject.doNotify();
return 0;
}
私のweak_ptr
スレッドセーフの使用法はありますか?ここからhttps://stackoverflow.com/a/2160422/1517648そうだと思います。
これは、失効したリスナーの問題を解決するための正当な方法ですか?