? bin ? stage Index: boost/signals/signal_template.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/signals/signal_template.hpp,v retrieving revision 1.17 diff -p -r1.17 signal_template.hpp *** boost/signals/signal_template.hpp 15 Dec 2004 22:07:17 -0000 1.17 --- boost/signals/signal_template.hpp 25 Jun 2005 00:13:06 -0000 *************** namespace boost { *** 137,142 **** --- 137,143 ---- BOOST_SIGNALS_TEMPLATE_ARGS> > class BOOST_SIGNALS_SIGNAL : + //public BOOST_SIGNALS_NAMESPACE::detail::signal_base >, // management of slot list public BOOST_SIGNALS_NAMESPACE::detail::signal_base, // management of slot list public BOOST_SIGNALS_NAMESPACE::trackable // signals are trackable { Index: boost/signals/detail/named_slot_map.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/signals/detail/named_slot_map.hpp,v retrieving revision 1.8 diff -p -r1.8 named_slot_map.hpp *** boost/signals/detail/named_slot_map.hpp 19 Apr 2005 13:50:53 -0000 1.8 --- boost/signals/detail/named_slot_map.hpp 25 Jun 2005 00:13:07 -0000 *************** class BOOST_SIGNALS_DECL named_slot_map_ *** 81,97 **** connection_slot_pair, forward_traversal_tag> inherited; public: ! named_slot_map_iterator(); ! named_slot_map_iterator(const named_slot_map_iterator&); ! named_slot_map_iterator& operator=(const named_slot_map_iterator&); ! ! connection_slot_pair& dereference() const; ! void increment(); ! bool equal(const named_slot_map_iterator& other) const; #if BOOST_WORKAROUND(BOOST_MSVC, <= 0x1701) ! void decrement(); ! void advance(difference_type); #endif private: --- 81,124 ---- connection_slot_pair, forward_traversal_tag> inherited; public: ! named_slot_map_iterator() : slot_assigned(false) {} ! connection_slot_pair& dereference() const { ! return *slot_; ! } ! ! named_slot_map_iterator(const named_slot_map_iterator& other) ! : group(other.group), last_group(other.last_group), ! slot_assigned(other.slot_assigned) ! { ! if (slot_assigned) slot_ = other.slot_; ! } ! named_slot_map_iterator& ! named_slot_map_iterator::operator=(const named_slot_map_iterator& other) ! { ! slot_assigned = other.slot_assigned; ! group = other.group; ! last_group = other.last_group; ! if (slot_assigned) slot_ = other.slot_; ! return *this; ! } ! ! void increment() { ! ++slot_; ! if (slot_ == group->second.end()) { ! ++group; ! init_next_group(); ! } ! } ! ! bool equal(const named_slot_map_iterator& other) const { ! return (group == other.group ! && (group == last_group ! || slot_ == other.slot_)); ! } #if BOOST_WORKAROUND(BOOST_MSVC, <= 0x1701) ! void decrement() { assert(false); } ! void advance(difference_type) { assert(false); } #endif private: *************** private: *** 100,106 **** { init_next_group(); } named_slot_map_iterator(group_iterator group, group_iterator last, slot_pair_iterator slot) : ! group(group), last_group(group), slot_(slot), slot_assigned(true) { } void init_next_group() --- 127,133 ---- { init_next_group(); } named_slot_map_iterator(group_iterator group, group_iterator last, slot_pair_iterator slot) : ! group(group), last_group(last), slot_(slot), slot_assigned(true) { } void init_next_group() *************** private: *** 122,143 **** class BOOST_SIGNALS_DECL named_slot_map { public: typedef named_slot_map_iterator iterator; ! named_slot_map(const compare_type& compare); - void clear(); - iterator begin(); - iterator end(); iterator insert(const any& name, const connection& con, const any& slot, ! connect_position at); ! void disconnect(const any& name); ! void erase(iterator pos); ! void remove_disconnected_slots(); private: - typedef std::list group_list; typedef std::map slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; --- 149,248 ---- class BOOST_SIGNALS_DECL named_slot_map { + typedef std::list group_list; + typedef group_list::iterator slot_pair_iterator; + public: typedef named_slot_map_iterator iterator; ! named_slot_map(const compare_type& compare) : groups(compare) { ! clear(); ! } ! ! void clear() { ! groups.clear(); ! groups[front_type()]; ! groups[back_type()]; ! back = groups.end(); ! --back; ! } ! ! iterator named_slot_map::begin() { ! return named_slot_map::iterator(groups.begin(), groups.end()); ! } ! ! iterator named_slot_map::end() { ! return named_slot_map::iterator(groups.end(), groups.end()); ! } iterator insert(const any& name, const connection& con, const any& slot, ! connect_position at) { ! group_iterator group; ! if (name.empty()) { ! switch (at) { ! case at_front: group = groups.begin(); break; ! case at_back: group = back; break; ! } ! } else { ! group = groups.find(name); ! if (group == groups.end()) { ! slot_container_type::value_type v(name, group_list()); ! group = groups.insert(v).first; ! } ! } ! iterator it; ! it.group = group; ! it.last_group = groups.end(); ! ! switch (at) { ! case at_back: ! group->second.push_back(connection_slot_pair(con, slot)); ! it.slot_ = group->second.end(); ! it.slot_assigned = true; ! --(it.slot_); ! break; ! ! case at_front: ! group->second.push_front(connection_slot_pair(con, slot)); ! it.slot_ = group->second.begin(); ! it.slot_assigned = true; ! break; ! } ! return it; ! } ! ! void disconnect(const any& name) { ! group_iterator group = groups.find(name); ! if (group != groups.end()) { ! slot_pair_iterator i = group->second.begin(); ! while (i != group->second.end()) { ! slot_pair_iterator next = i; ! ++next; ! i->first.disconnect(); ! i = next; ! } ! groups.erase(group); ! } ! } ! void erase(iterator pos) { pos.slot_->first.disconnect(); } ! void remove_disconnected_slots() { ! // Remove any disconnected slots ! group_iterator g = groups.begin(); ! while (g != groups.end()) { ! slot_pair_iterator s = g->second.begin(); ! while (s != g->second.end()) { ! if (s->first.connected()) ++s; ! else g->second.erase(s++); ! } ! ! // Clear out empty groups ! if (empty(g)) groups.erase(g++); ! else ++g; ! } ! } ! private: typedef std::map slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; Index: boost/signals/detail/signal_base.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/signals/detail/signal_base.hpp,v retrieving revision 1.14 diff -p -r1.14 signal_base.hpp *** boost/signals/detail/signal_base.hpp 1 Oct 2004 02:07:33 -0000 1.14 --- boost/signals/detail/signal_base.hpp 25 Jun 2005 00:13:07 -0000 *************** namespace boost { *** 32,44 **** namespace detail { // Must be constructed before calling the slots, because it safely // manages call depth ! class BOOST_SIGNALS_DECL call_notification { ! public: ! call_notification(const shared_ptr&); ! ~call_notification(); ! ! shared_ptr impl; ! }; // Implementation of base class for all signals. It handles the // management of the underlying slot lists. --- 32,38 ---- namespace detail { // Must be constructed before calling the slots, because it safely // manages call depth ! class call_notification; // Implementation of base class for all signals. It handles the // management of the underlying slot lists. *************** namespace boost { *** 56,62 **** { base->flags.clearing = true; } - ~temporarily_set_clearing() { base->flags.clearing = false; --- 50,55 ---- *************** namespace boost { *** 68,99 **** friend class temporarily_set_clearing; ! signal_base_impl(const compare_type&, const any&); ! ~signal_base_impl(); ! // Disconnect all slots connected to this signal ! void disconnect_all_slots(); // Are there any connected slots? ! bool empty() const; // The number of connected slots ! std::size_t num_slots() const; // Disconnect all slots in the given group ! void disconnect(const any&); // We're being notified that a slot has disconnected ! static void slot_disconnected(void* obj, void* data); ! ! connection connect_slot(const any& slot, const any& name, shared_ptr data, ! connect_position at); private: // Remove all of the slots that have been marked "disconnected" ! void remove_disconnected_slots() const; public: // Our call depth when invoking slots (> 1 when we have a loop) --- 61,207 ---- friend class temporarily_set_clearing; ! 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; ! } ! ! signal_base_impl::~signal_base_impl() ! { ! // Set the "clearing" flag to ignore extraneous disconnect requests, ! // because all slots will be disconnected on destruction anyway. ! flags.clearing = true; ! } ! // Disconnect all slots connected to this signal ! void signal_base_impl::disconnect_all_slots() ! { ! // Do nothing if we're already clearing the slot list ! if (flags.clearing) ! return; ! ! if (call_depth == 0) { ! // Clearing the slot list will disconnect all slots automatically ! temporarily_set_clearing set_clearing(this); ! slots_.clear(); ! } ! else { ! // We can't actually remove elements from the slot list because there ! // are still iterators into the slot list that must not be ! // invalidated by this operation. So just disconnect each slot ! // without removing it from the slot list. When the call depth does ! // reach zero, the call list will be cleared. ! flags.delayed_disconnect = true; ! temporarily_set_clearing set_clearing(this); ! for (iterator i = slots_.begin(); i != slots_.end(); ++i) { ! i->first.disconnect(); ! } ! } ! } // Are there any connected slots? ! 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 (iterator i = slots_.begin(); i != slots_.end(); ++i) { ! if (i->first.connected()) ! return false; ! } ! ! return true; ! } // The number of connected slots ! std::size_t signal_base_impl::num_slots() 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 ! std::size_t count = 0; ! for (iterator i = slots_.begin(); i != slots_.end(); ++i) { ! if (i->first.connected()) ! ++count; ! } ! return count; ! } // Disconnect all slots in the given group ! void signal_base_impl::disconnect(const any& group) ! { slots_.disconnect(group); } // We're being notified that a slot has disconnected ! static void signal_base_impl::slot_disconnected(void* obj, void* data) ! { ! signal_base_impl* self = reinterpret_cast(obj); ! ! // We won't need the slot iterator after this ! std::auto_ptr slot(reinterpret_cast(data)); ! ! // If we're flags.clearing, we don't bother updating the list of slots ! if (!self->flags.clearing) { ! // If we're in a call, note the fact that a slot has been deleted so ! // we can come back later to remove the iterator ! if (self->call_depth > 0) { ! self->flags.delayed_disconnect = true; ! } ! else { ! // Just remove the slot now, it's safe ! self->slots_.erase(*slot); ! } ! } ! } ! connection connect_slot(const any& slot_, const any& name, shared_ptr 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. ! std::auto_ptr saved_iter(new iterator); ! ! // 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(); ! } ! private: // Remove all of the slots that have been marked "disconnected" ! void remove_disconnected_slots() const ! { slots_.remove_disconnected_slots(); } public: // Our call depth when invoking slots (> 1 when we have a loop) *************** namespace boost { *** 117,132 **** typedef named_slot_map::iterator iterator; }; class BOOST_SIGNALS_DECL signal_base : public noncopyable { public: typedef signal_base_impl::compare_type compare_type; friend class call_notification; ! signal_base(const compare_type& comp, const any& combiner); ! ~signal_base(); - public: // Disconnect all slots connected to this signal void disconnect_all_slots() { impl->disconnect_all_slots(); } --- 225,271 ---- typedef named_slot_map::iterator iterator; }; + class BOOST_SIGNALS_DECL call_notification { + public: + call_notification(const shared_ptr& b) : + impl(b) + { + // A call will be made, so increment the call depth as a notification + impl->call_depth++; + } + + ~call_notification() { + { + impl->call_depth--; + + // If the call depth is zero and we have some slots that have been + // disconnected during the calls, remove those slots from the list + if (impl->call_depth == 0 && + impl->flags.delayed_disconnect) { + impl->remove_disconnected_slots(); + impl->flags.delayed_disconnect = false; + } + } + } + shared_ptr impl; + }; + class BOOST_SIGNALS_DECL signal_base : public noncopyable { public: typedef signal_base_impl::compare_type compare_type; friend class call_notification; ! signal_base::signal_base(const compare_type& comp, const any& combiner) ! : impl() ! { ! impl.reset(new signal_base_impl(comp, combiner)); ! } ! ! signal_base::~signal_base() ! { ! } // Disconnect all slots connected to this signal void disconnect_all_slots() { impl->disconnect_all_slots(); } Index: libs/signals/src/named_slot_map.cpp =================================================================== RCS file: /cvsroot/boost/boost/libs/signals/src/named_slot_map.cpp,v retrieving revision 1.10 diff -p -r1.10 named_slot_map.cpp *** libs/signals/src/named_slot_map.cpp 19 Apr 2005 13:50:54 -0000 1.10 --- libs/signals/src/named_slot_map.cpp 25 Jun 2005 00:13:16 -0000 *************** *** 17,174 **** namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { typedef std::list group_list; typedef group_list::iterator slot_pair_iterator; typedef std::map slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; - named_slot_map_iterator::named_slot_map_iterator() : slot_assigned(false) {} - - named_slot_map_iterator:: - named_slot_map_iterator(const named_slot_map_iterator& other) - : group(other.group), last_group(other.last_group), - slot_assigned(other.slot_assigned) - { - if (slot_assigned) slot_ = other.slot_; - } - - named_slot_map_iterator& - named_slot_map_iterator::operator=(const named_slot_map_iterator& other) - { - slot_assigned = other.slot_assigned; - group = other.group; - last_group = other.last_group; - if (slot_assigned) slot_ = other.slot_; - return *this; - } - - - connection_slot_pair& named_slot_map_iterator::dereference() const - { return *slot_; } - - void named_slot_map_iterator::increment() - { - ++slot_; - if (slot_ == group->second.end()) { - ++group; - init_next_group(); - } - } - - bool - named_slot_map_iterator::equal(const named_slot_map_iterator& other) const - { - return (group == other.group - && (group == last_group - || slot_ == other.slot_)); - } - - #if BOOST_WORKAROUND(BOOST_MSVC, <= 0x1701) - void named_slot_map_iterator::decrement() { assert(false); } - void named_slot_map_iterator::advance(difference_type) { assert(false); } - #endif - - named_slot_map::named_slot_map(const compare_type& compare) : groups(compare) - { - clear(); - } - - void named_slot_map::clear() - { - groups.clear(); - groups[front_type()]; - groups[back_type()]; - back = groups.end(); - --back; - } - - named_slot_map::iterator named_slot_map::begin() - { - return named_slot_map::iterator(groups.begin(), groups.end()); - } - - named_slot_map::iterator named_slot_map::end() - { - return named_slot_map::iterator(groups.end(), groups.end()); - } - - named_slot_map::iterator - named_slot_map::insert(const any& name, const connection& con, const any& slot, - connect_position at) - { - group_iterator group; - if (name.empty()) { - switch (at) { - case at_front: group = groups.begin(); break; - case at_back: group = back; break; - } - } else { - group = groups.find(name); - if (group == groups.end()) { - slot_container_type::value_type v(name, group_list()); - group = groups.insert(v).first; - } - } - iterator it; - it.group = group; - it.last_group = groups.end(); - - switch (at) { - case at_back: - group->second.push_back(connection_slot_pair(con, slot)); - it.slot_ = group->second.end(); - it.slot_assigned = true; - --(it.slot_); - break; - - case at_front: - group->second.push_front(connection_slot_pair(con, slot)); - it.slot_ = group->second.begin(); - it.slot_assigned = true; - break; - } - return it; - } - - void named_slot_map::disconnect(const any& name) - { - group_iterator group = groups.find(name); - if (group != groups.end()) { - slot_pair_iterator i = group->second.begin(); - while (i != group->second.end()) { - slot_pair_iterator next = i; - ++next; - i->first.disconnect(); - i = next; - } - groups.erase(group); - } - } - - void named_slot_map::erase(iterator pos) - { - // Erase the slot - pos.slot_->first.disconnect(); - // pos.impl_->group->second.erase(pos.impl_->slot_); ? - } - - void named_slot_map::remove_disconnected_slots() - { - // Remove any disconnected slots - group_iterator g = groups.begin(); - while (g != groups.end()) { - slot_pair_iterator s = g->second.begin(); - while (s != g->second.end()) { - if (s->first.connected()) ++s; - else g->second.erase(s++); - } - - // Clear out empty groups - if (empty(g)) groups.erase(g++); - else ++g; - } - } } } } --- 17,30 ---- namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { + /* typedef std::list group_list; typedef group_list::iterator slot_pair_iterator; typedef std::map slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; + */ } } } Index: libs/signals/src/signal_base.cpp =================================================================== RCS file: /cvsroot/boost/boost/libs/signals/src/signal_base.cpp,v retrieving revision 1.14 diff -p -r1.14 signal_base.cpp *** libs/signals/src/signal_base.cpp 28 Nov 2004 04:27:35 -0000 1.14 --- libs/signals/src/signal_base.cpp 25 Jun 2005 00:13:16 -0000 *************** *** 15,187 **** namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { - 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; - } - signal_base_impl::~signal_base_impl() - { - // Set the "clearing" flag to ignore extraneous disconnect requests, - // because all slots will be disconnected on destruction anyway. - flags.clearing = true; - } - - void signal_base_impl::disconnect_all_slots() - { - // Do nothing if we're already clearing the slot list - if (flags.clearing) - return; - - if (call_depth == 0) { - // Clearing the slot list will disconnect all slots automatically - temporarily_set_clearing set_clearing(this); - slots_.clear(); - } - else { - // We can't actually remove elements from the slot list because there - // are still iterators into the slot list that must not be - // invalidated by this operation. So just disconnect each slot - // without removing it from the slot list. When the call depth does - // reach zero, the call list will be cleared. - flags.delayed_disconnect = true; - temporarily_set_clearing set_clearing(this); - for (iterator i = slots_.begin(); i != slots_.end(); ++i) { - i->first.disconnect(); - } - } - } - - connection - signal_base_impl:: - connect_slot(const any& slot_, - const any& name, - shared_ptr 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. - std::auto_ptr saved_iter(new iterator); - - // 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(); - } - - 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 (iterator i = slots_.begin(); i != slots_.end(); ++i) { - if (i->first.connected()) - return false; - } - - return true; - } - - std::size_t signal_base_impl::num_slots() 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 - std::size_t count = 0; - for (iterator i = slots_.begin(); i != slots_.end(); ++i) { - if (i->first.connected()) - ++count; - } - return count; - } - - void signal_base_impl::disconnect(const any& group) - { slots_.disconnect(group); } - - void signal_base_impl::slot_disconnected(void* obj, void* data) - { - signal_base_impl* self = reinterpret_cast(obj); - - // We won't need the slot iterator after this - std::auto_ptr slot(reinterpret_cast(data)); - - // If we're flags.clearing, we don't bother updating the list of slots - if (!self->flags.clearing) { - // If we're in a call, note the fact that a slot has been deleted so - // we can come back later to remove the iterator - if (self->call_depth > 0) { - self->flags.delayed_disconnect = true; - } - else { - // Just remove the slot now, it's safe - self->slots_.erase(*slot); - } - } - } - - void signal_base_impl::remove_disconnected_slots() const - { slots_.remove_disconnected_slots(); } - - call_notification:: - call_notification(const shared_ptr& b) : - impl(b) - { - // A call will be made, so increment the call depth as a notification - impl->call_depth++; - } - - call_notification::~call_notification() - { - impl->call_depth--; - - // If the call depth is zero and we have some slots that have been - // disconnected during the calls, remove those slots from the list - if (impl->call_depth == 0 && - impl->flags.delayed_disconnect) { - impl->remove_disconnected_slots(); - impl->flags.delayed_disconnect = false; - } - } - - signal_base::signal_base(const compare_type& comp, const any& combiner) - : impl() - { - impl.reset(new signal_base_impl(comp, combiner)); - } - - signal_base::~signal_base() - { - } } // namespace detail } // namespace BOOST_SIGNALS_NAMESPACE --- 15,21 ----