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); }
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(); }