Chris@16: // Boost.Signals library Chris@16: Chris@16: // Copyright Douglas Gregor 2001-2004. Use, modification and Chris@16: // distribution is subject to the Boost Software License, Version Chris@16: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // For more information, see http://www.boost.org Chris@16: Chris@16: #ifndef BOOST_SIGNALS_NAMED_SLOT_MAP_HPP Chris@16: #define BOOST_SIGNALS_NAMED_SLOT_MAP_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace BOOST_SIGNALS_NAMESPACE { Chris@16: Chris@16: enum connect_position { at_back, at_front }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: class stored_group Chris@16: { Chris@16: public: Chris@16: enum storage_kind { sk_empty, sk_front, sk_back, sk_group }; Chris@16: Chris@16: stored_group(storage_kind p_kind = sk_empty) : kind(p_kind), group() { } Chris@16: Chris@16: template Chris@16: stored_group(const T& p_group) : kind(sk_group), group(new T(p_group)) { } Chris@16: Chris@16: bool is_front() const { return kind == sk_front; } Chris@16: bool is_back() const { return kind == sk_back; } Chris@16: bool empty() const { return kind == sk_empty; } Chris@16: Chris@16: void* get() const { return group.get(); } Chris@16: Chris@16: private: Chris@16: storage_kind kind; Chris@16: shared_ptr group; Chris@16: }; Chris@16: Chris@16: typedef function2 compare_type; Chris@16: Chris@16: // This function object bridges from a pair of any objects that hold Chris@16: // values of type Key to the underlying function object that compares Chris@16: // values of type Key. Chris@16: template Chris@16: class group_bridge_compare { Chris@16: public: Chris@16: typedef bool result_type; Chris@16: typedef const stored_group& first_argument_type; Chris@16: typedef const stored_group& second_argument_type; Chris@16: Chris@101: group_bridge_compare(const Compare& c) : comp(c) Chris@16: { } Chris@16: Chris@16: bool operator()(const stored_group& k1, const stored_group& k2) const Chris@16: { Chris@16: if (k1.is_front()) return !k2.is_front(); Chris@16: if (k1.is_back()) return false; Chris@16: if (k2.is_front()) return false; Chris@16: if (k2.is_back()) return true; Chris@16: Chris@16: // Neither is empty, so compare their values to order them Chris@16: return comp(*static_cast(k1.get()), *static_cast(k2.get())); Chris@16: } Chris@16: Chris@16: private: Chris@16: Compare comp; Chris@16: }; Chris@16: Chris@16: class BOOST_SIGNALS_DECL named_slot_map_iterator : Chris@16: public iterator_facade Chris@16: { Chris@16: typedef std::list group_list; Chris@16: typedef group_list::iterator slot_pair_iterator; Chris@16: typedef std::map slot_container_type; Chris@16: typedef slot_container_type::iterator group_iterator; Chris@16: typedef slot_container_type::const_iterator const_group_iterator; Chris@16: Chris@16: typedef iterator_facade inherited; Chris@16: public: Chris@101: named_slot_map_iterator() : slot_assigned(false) Chris@16: { } Chris@101: named_slot_map_iterator(const named_slot_map_iterator& other) Chris@16: : group(other.group), last_group(other.last_group), Chris@16: slot_assigned(other.slot_assigned) Chris@16: { Chris@16: if (slot_assigned) slot_ = other.slot_; Chris@16: } Chris@101: named_slot_map_iterator& operator=(const named_slot_map_iterator& other) Chris@16: { Chris@16: slot_assigned = other.slot_assigned; Chris@16: group = other.group; Chris@16: last_group = other.last_group; Chris@16: if (slot_assigned) slot_ = other.slot_; Chris@16: return *this; Chris@16: } Chris@101: connection_slot_pair& dereference() const Chris@16: { Chris@16: return *slot_; Chris@16: } Chris@101: void increment() Chris@16: { Chris@16: ++slot_; Chris@16: if (slot_ == group->second.end()) { Chris@16: ++group; Chris@16: init_next_group(); Chris@16: } Chris@16: } Chris@16: bool equal(const named_slot_map_iterator& other) const { Chris@16: return (group == other.group Chris@16: && (group == last_group Chris@16: || slot_ == other.slot_)); Chris@16: } Chris@16: Chris@101: #if BOOST_WORKAROUND(_MSC_VER, <= 1900) Chris@16: void decrement(); Chris@16: void advance(difference_type); Chris@16: #endif Chris@16: Chris@16: private: Chris@16: named_slot_map_iterator(group_iterator giter, group_iterator last) : Chris@16: group(giter), last_group(last), slot_assigned(false) Chris@16: { init_next_group(); } Chris@16: named_slot_map_iterator(group_iterator giter, group_iterator last, Chris@16: slot_pair_iterator slot) : Chris@16: group(giter), last_group(last), slot_(slot), slot_assigned(true) Chris@16: { } Chris@16: Chris@16: void init_next_group() Chris@16: { Chris@16: while (group != last_group && group->second.empty()) ++group; Chris@16: if (group != last_group) { Chris@16: slot_ = group->second.begin(); Chris@16: slot_assigned = true; Chris@16: } Chris@16: } Chris@16: Chris@16: group_iterator group; Chris@16: group_iterator last_group; Chris@16: slot_pair_iterator slot_; Chris@16: bool slot_assigned; Chris@16: Chris@16: friend class named_slot_map; Chris@16: }; Chris@16: Chris@16: class BOOST_SIGNALS_DECL named_slot_map Chris@16: { Chris@16: public: Chris@16: typedef named_slot_map_iterator iterator; Chris@16: Chris@16: named_slot_map(const compare_type& compare); Chris@16: Chris@16: void clear(); Chris@16: iterator begin(); Chris@16: iterator end(); Chris@16: iterator insert(const stored_group& name, const connection& con, Chris@16: const any& slot, connect_position at); Chris@16: void disconnect(const stored_group& name); Chris@16: void erase(iterator pos); Chris@16: void remove_disconnected_slots(); Chris@16: Chris@16: private: Chris@16: typedef std::list group_list; Chris@16: typedef std::map slot_container_type; Chris@16: typedef slot_container_type::iterator group_iterator; Chris@16: typedef slot_container_type::const_iterator const_group_iterator; Chris@16: Chris@16: bool empty(const_group_iterator group) const Chris@16: { Chris@16: return (group->second.empty() && group != groups.begin() && group != back); Chris@16: } Chris@16: slot_container_type groups; Chris@16: group_iterator back; Chris@16: }; Chris@16: Chris@16: } } } Chris@16: Chris@16: #endif // BOOST_SIGNALS_NAMED_SLOT_MAP_HPP