Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I'd be a bit leery of your <code>doNotify</code> -- suppose something in an observer you fire ends up adding or removing observers? -- bad things happen (including crashes). Or blocking on the action of another thread, who blocks on trying to add an observer? -- bad things happen (deadlocks!)</p> <p>This is tricky to solve. Basically, it is a problem with reentrancy.</p> <p>Never, ever leave control of your code when you hold a lock. Holding a lock while calling a callback is a no-no.</p> <p>So, at a minimum:</p> <p>Lock then Copy your list then Unlock. While doing this copy, you can also remove expired observers (from both the original, and the copy, list).</p> <p>Then fire off observers from the copied list.</p> <p>This leaves some problems unresolved. Such as the fact that removing an observer does not guarantee that it won't be called in the future! It just means that eventually it won't be called.</p> <p>How important that is depends on how you use listening.</p> <p>One approach that might work is a task queue that includes add/remove/notify/killthread events (making killthread a task in the queue makes shutting down far less annoying). Now all synchronization is on the queue. If you aren't up to writing a non-blocking lock-free queue, the notify code can simply lock, <code>std::move</code> the queue, unlock, then proceeds to execute it. Or you could write a queue such that <code>pop</code> blocks until there is something to read, and <code>push</code> doesn't block.</p> <p>A quick-and-dirty "copy and broadcast" might look like this: </p> <pre><code>std::vector&lt;std::shared_ptr&lt;IObserver&gt;&gt; targets; { std::lock_guard&lt;std::mutex&gt; guard( m_observersMutex ); m_observers.erase( std::remove_if( m_observers.begin(), m_observers.end(), [&amp;targets]( const std::weak_ptr&lt;IObserver&gt;&amp; o ) { std::shared_ptr&lt;IObserver&gt; ptr = o.lock(); if (ptr) { targets.push_back(ptr); return false; } else { return true; } } ), m_observers.end() ); } for( auto&amp; target:targets ) { target-&gt;notify(); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload