// Boost.Signals library
-// Copyright Doug Gregor 2001-2003. Use, modification and
+// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
namespace boost {
namespace BOOST_SIGNALS_NAMESPACE {
namespace detail {
- signal_base_impl::signal_base_impl(const compare_type& comp) :
- call_depth(0),
- slots_(comp)
+ signal_base_impl::signal_base_impl(const compare_type& comp,
+ const any& combiner)
+ : call_depth(0),
+ slots_(comp),
+ combiner_(combiner)
{
flags.delayed_disconnect = false;
flags.clearing = false;
// reach zero, the call list will be cleared.
flags.delayed_disconnect = true;
temporarily_set_clearing set_clearing(this);
- for (slot_iterator i = slots_.begin(); i != slots_.end(); ++i) {
- i->second.first.disconnect();
+ for (iterator i = slots_.begin(); i != slots_.end(); ++i) {
+ i->first.disconnect();
}
}
}
connection
signal_base_impl::
- connect_slot(const any& slot,
+ connect_slot(const any& slot_,
const any& name,
- const std::vector<const trackable*>& bound_objects)
+ shared_ptr<slot_base::data_t> data,
+ connect_position at)
{
- // Allocate storage for a new basic_connection object to represent the
- // connection
- basic_connection* con = new basic_connection();
-
- // Create a new connection handle object and place the basic_connection
- // object we just created under its control. Note that the "reset"
- // routine will delete con if allocation throws.
- connection slot_connection;
- slot_connection.reset(con);
+ // 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.
- std::auto_ptr<slot_iterator> saved_iter(new slot_iterator());
+ std::auto_ptr<iterator> saved_iter(new iterator);
// Add the slot to the list.
-
- slot_iterator pos =
- slots_.insert(stored_slot_type(name,
- connection_slot_pair(slot_connection,
- slot)));
-
- // Make the copy of the connection in the list disconnect when it is
- // destroyed
- pos->second.first.set_controlling();
+ 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
// Fill out the connection object appropriately. None of these
// operations can throw
- con->signal = this;
- con->signal_data = saved_iter.release();
- con->signal_disconnect = &signal_base_impl::slot_disconnected;
-
- // If an exception is thrown the connection will automatically be
- // disconnected.
- scoped_connection safe_connection = slot_connection;
-
- // Connect each of the bound objects
- for(std::vector<const trackable*>::const_iterator i =
- bound_objects.begin();
- i != bound_objects.end();
- ++i) {
- // Notify the object that the signal is connecting to it by passing
- // it a copy of the connection. If the connection
- // should throw, the scoped connection safe_connection will
- // disconnect the connection completely.
- bound_object binding;
- (*i)->signal_connected(slot_connection, 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
- 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, and we must not
- // disconnect the connection now
- safe_connection.release();
+ 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;
- return slot_connection;
+ // 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();
}
bool signal_base_impl::empty() const
// Disconnected slots may still be in the list of slots if
// a) this is called while slots are being invoked (call_depth > 0)
// b) an exception was thrown in remove_disconnected_slots
- for (slot_iterator i = slots_.begin(); i != slots_.end(); ++i) {
- if (i->second.first.connected())
+ for (iterator i = slots_.begin(); i != slots_.end(); ++i) {
+ if (i->first.connected())
return false;
}
// a) this is called while slots are being invoked (call_depth > 0)
// b) an exception was thrown in remove_disconnected_slots
std::size_t count = 0;
- for (slot_iterator i = slots_.begin(); i != slots_.end(); ++i) {
- if (i->second.first.connected())
+ for (iterator i = slots_.begin(); i != slots_.end(); ++i) {
+ if (i->first.connected())
++count;
}
return count;
}
void signal_base_impl::disconnect(const any& group)
- {
- std::pair<slot_iterator, slot_iterator> group_slots =
- slots_.equal_range(group);
- while (group_slots.first != group_slots.second) {
- slot_iterator next = group_slots.first;
- ++next;
-
- group_slots.first->second.first.disconnect();
- group_slots.first = next;
- }
- }
+ { slots_.disconnect(group); }
void signal_base_impl::slot_disconnected(void* obj, void* data)
{
signal_base_impl* self = reinterpret_cast<signal_base_impl*>(obj);
// We won't need the slot iterator after this
- std::auto_ptr<slot_iterator> slot(
- reinterpret_cast<slot_iterator*>(data));
+ std::auto_ptr<iterator> slot(reinterpret_cast<iterator*>(data));
// If we're flags.clearing, we don't bother updating the list of slots
if (!self->flags.clearing) {
}
void signal_base_impl::remove_disconnected_slots() const
- {
- // Remove any disconnected slots
- for (slot_iterator i = slots_.begin(); i != slots_.end(); /* none */) {
- if (!i->second.first.connected())
- slots_.erase(i++);
- else
- ++i;
- }
- }
+ { slots_.remove_disconnected_slots(); }
call_notification::
call_notification(const shared_ptr<signal_base_impl>& b) :
}
}
- signal_base::signal_base(const compare_type& comp) : impl()
+ signal_base::signal_base(const compare_type& comp, const any& combiner)
+ : impl()
{
- impl.reset(new signal_base_impl(comp));
+ impl.reset(new signal_base_impl(comp, combiner));
}
signal_base::~signal_base()
} // namespace BOOST_SIGNALS_NAMESPACE
} // namespace boost
-#ifndef BOOST_MSVC
-// Explicit instantiations to keep in the library
-template class boost::function2<bool, boost::any, boost::any>;
-template class std::multimap<boost::any,
- boost::BOOST_SIGNALS_NAMESPACE::detail::connection_slot_pair,
- boost::function2<bool, boost::any, boost::any> >;
-#endif