Force deletion of slot in boost::signals2

前端 未结 5 1171
清歌不尽
清歌不尽 2021-02-05 20:13

I have found that boost::signals2 uses sort of a lazy deletion of connected slots, which makes it difficult to use connections as something that manages lifetimes of objects. I

5条回答
  •  醉酒成梦
    2021-02-05 21:03

    I stumbled upon the same problem and i really miss some kind of explicit cleanup in the API.

    In my scenario i am unloading some plug-in dll's and i have to assure there are no dangling objects (slots) which refer to code (vftables or whatsoever) living in the unloaded dll. Simply disconnecting slots didn't work due to the lazy deletion stuff.

    My first workaround was a signal wrapper which tweaks the disconnecting code a little bit:

    template 
    struct MySignal
    {
      // ...
    
      template 
      void disconnect (Slot&& s)
      {
        mPrivate.disconnect (forward (s));
        // connect/disconnect dummy slot to force cleanup of s
        mPrivate.connect (&MySignal::foo);
        mPrivate.disconnect (&MySignal::foo);
      }
    
    private:
      // dummy slot function with matching signature
      // ... foo (...)
    
    private:
      ::boost::signals2::signal mPrivate;
    };
    

    Unfortunately this didn't work because connect() only does some cleanup. It doesn't guarantee cleanup of all unconnected slots. Signal invocation on the other hand does a full cleanup but a dummy invocation would also be an unacceptable behavioral change (as already mentioned by others).

    In the absence of alternatives i ended up in patching the original signal class (Edit: i really would appreciate a built-in solution. this patch was my last resort). My patch is around 10 lines of code and adds a public cleanup_connections() method to signal. My signal wrapper invokes the cleanup at the end of the disconnecting methods. This approach solved my problems and i didn't encounter any performance problems so far.

    Edit: Here is my patch for boost 1.5.3

    Index: signals2/detail/signal_template.hpp
    ===================================================================
    --- signals2/detail/signal_template.hpp
    +++ signals2/detail/signal_template.hpp
    @@ -220,6 +220,15 @@
               typedef mpl::bool_<(is_convertible::value)> is_group;
               do_disconnect(slot, is_group());
             }
    +        void cleanup_connections () const
    +        {
    +          unique_lock list_lock(_mutex);
    +          if(_shared_state.unique() == false)
    +          {
    +            _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
    +          }
    +          nolock_cleanup_connections_from(false, _shared_state->connection_bodies().begin());
    +        }
             // emit signal
             result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
             {
    @@ -690,6 +699,10 @@
           {
             (*_pimpl).disconnect(slot);
           }
    +      void cleanup_connections ()
    +      {
    +        (*_pimpl).cleanup_connections();
    +      }
           result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
           {
             return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
    

提交回复
热议问题