Example #1
0
      void slot_base::create_connection()
      {
        // Create a new connection object
        basic_connection* con = new basic_connection();

        /* nothrow */ {
          // The signal portion isn't really necessary, except that we need a
          // signal for the connection to be connected.
          con->signal = static_cast<void*>(this);
          con->signal_data = 0;
          con->signal_disconnect = &bound_object_destructed;
        }

        // This connection watches for destruction of bound objects. Note
        // that the reset routine will delete con if an allocation throws
        data->watch_bound_objects.reset(con);

        // We create a scoped connection, so that exceptions thrown while
        // adding bound objects will cause a cleanup of the bound objects
        // already connected.
        scoped_connection safe_connection(data->watch_bound_objects);

        // Now notify each of the bound objects that they are connected to this
        // slot.
        for(std::vector<const trackable*>::iterator i = 
              data->bound_objects.begin(); 
            i != data->bound_objects.end(); ++i) {
          // Notify the object that the slot is connecting to it
          BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;
          (*i)->signal_connected(data->watch_bound_objects, binding);

          // This will notify the bound object that the connection just made
          // should be disconnected if an exception is thrown before the
          // end of this iteration
          BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object
            disconnector(binding);

          // Add the binding to the list of bindings for the connection
          con->bound_objects.push_back(binding);

          // The connection object now knows about the bound object, so if an
          // exception is thrown later the connection object will notify the
          // bound object of the disconnection automatically
          disconnector.release();
        }

        // No exceptions will be thrown past this point.
        safe_connection.release();

        data->watch_bound_objects.set_controlling(true);
      }
Example #2
0
      connection
      signal_base_impl::
        connect_slot(const any& slot_,
                     const stored_group& name,
                     shared_ptr<slot_base::data_t> data,
                     connect_position at)
      {
        // Transfer the burden of ownership to a local, scoped
        // connection.
        data->watch_bound_objects.set_controlling(false);
        scoped_connection safe_connection(data->watch_bound_objects);

        // Allocate storage for an iterator that will hold the point of
        // insertion of the slot into the list. This is used to later remove
        // the slot when it is disconnected.

#if defined(BOOST_NO_CXX11_SMART_PTR)

        std::auto_ptr<iterator> saved_iter(new iterator);

#else

        std::unique_ptr<iterator> saved_iter(new iterator);

#endif

        // Add the slot to the list.
        iterator pos =
          slots_.insert(name, data->watch_bound_objects, slot_, at);

        // The assignment operation here absolutely must not throw, which
        // intuitively makes sense (because any container's insert method
        // becomes impossible to use in an exception-safe manner without this
        // assumption), but doesn't appear to be mentioned in the standard.
        *saved_iter = pos;

        // Fill out the connection object appropriately. None of these
        // operations can throw
        data->watch_bound_objects.get_connection()->signal = this;
        data->watch_bound_objects.get_connection()->signal_data =
          saved_iter.release();
        data->watch_bound_objects.get_connection()->signal_disconnect =
          &signal_base_impl::slot_disconnected;

        // Make the copy of the connection in the list disconnect when it is
        // destroyed. The local, scoped connection is then released
        // because ownership has been transferred.
        pos->first.set_controlling();
        return safe_connection.release();
      }