// Boost.Signals library // 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) // For more information, see http://www.boost.org #ifndef BOOST_SIGNALS_NAMED_SLOT_MAP_HPP #define BOOST_SIGNALS_NAMED_SLOT_MAP_HPP #include <boost/signals/detail/config.hpp> #include <boost/signals/detail/signals_common.hpp> #include <boost/signals/connection.hpp> #include <boost/utility.hpp> #include <boost/shared_ptr.hpp> #include <boost/function/function2.hpp> #include <boost/iterator/iterator_facade.hpp> #include <map> #include <memory> #include <utility> namespace boost { namespace BOOST_SIGNALS_NAMESPACE { enum connect_position { at_back, at_front }; namespace detail { class stored_group { public: enum storage_kind { sk_empty, sk_front, sk_back, sk_group }; stored_group(storage_kind kind = sk_empty) : kind(kind), group() { } template<typename T> stored_group(const T& group) : kind(sk_group), group(new T(group)) { } bool is_front() const { return kind == sk_front; } bool is_back() const { return kind == sk_back; } bool empty() const { return kind == sk_empty; } void* get() const { return group.get(); } private: storage_kind kind; shared_ptr<void> group; }; typedef function2<bool, stored_group, stored_group> compare_type; // This function object bridges from a pair of any objects that hold // values of type Key to the underlying function object that compares // values of type Key. template<typename Compare, typename Key> class group_bridge_compare { public: typedef bool result_type; typedef const stored_group& first_argument_type; typedef const stored_group& second_argument_type; group_bridge_compare(const Compare& c) : comp(c) { } bool operator()(const stored_group& k1, const stored_group& k2) const { if (k1.is_front()) return !k2.is_front(); if (k1.is_back()) return false; if (k2.is_front()) return false; if (k2.is_back()) return true; // Neither is empty, so compare their values to order them return comp(*static_cast<Key*>(k1.get()), *static_cast<Key*>(k2.get())); } private: Compare comp; }; class BOOST_SIGNALS_DECL named_slot_map_iterator : public iterator_facade<named_slot_map_iterator, connection_slot_pair, forward_traversal_tag> { typedef std::list<connection_slot_pair> group_list; typedef group_list::iterator slot_pair_iterator; typedef std::map<stored_group, group_list, compare_type> slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; typedef iterator_facade<named_slot_map_iterator, connection_slot_pair, forward_traversal_tag> inherited; public: named_slot_map_iterator() : slot_assigned(false) { } 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& 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& dereference() const { return *slot_; } 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(_MSC_VER, <= 1600) void decrement(); void advance(difference_type); #endif private: named_slot_map_iterator(group_iterator group, group_iterator last) : group(group), last_group(last), slot_assigned(false) { 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() { while (group != last_group && group->second.empty()) ++group; if (group != last_group) { slot_ = group->second.begin(); slot_assigned = true; } } group_iterator group; group_iterator last_group; slot_pair_iterator slot_; bool slot_assigned; friend class named_slot_map; }; 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 stored_group& name, const connection& con, const any& slot, connect_position at); void disconnect(const stored_group& name); void erase(iterator pos); void remove_disconnected_slots(); private: typedef std::list<connection_slot_pair> group_list; typedef std::map<stored_group, group_list, compare_type> slot_container_type; typedef slot_container_type::iterator group_iterator; typedef slot_container_type::const_iterator const_group_iterator; bool empty(const_group_iterator group) const { return (group->second.empty() && group != groups.begin() && group != back); } slot_container_type groups; group_iterator back; }; } } } #endif // BOOST_SIGNALS_NAMED_SLOT_MAP_HPP