From 1682b1ade7966d819734753345fc22c6af4836a7 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 6 Jul 2014 22:00:51 +0200 Subject: [PATCH] Use the new tree class instead of a flat array. This is so that observers being registered can refer "sub-observers" recursively. When such observer is deleted, the whole underlying subtree is removed with it. This facilitates the process of unregistering observers - ie: when the main observer goes down because it is destroyed, all of its sub-observers are removed as well, because in this architecture they are expected to be aggregated to the main observer. --- src/observersmanager.hpp | 91 ++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/src/observersmanager.hpp b/src/observersmanager.hpp index 40d08f3..b5340ef 100644 --- a/src/observersmanager.hpp +++ b/src/observersmanager.hpp @@ -20,54 +20,109 @@ #ifndef idF5E41734950640CDA3C949E0D3A9A30D #define idF5E41734950640CDA3C949E0D3A9A30D -#include "linearmap.hpp" #include #include #include #include #include +#include +#include namespace cloonel { template class ObserversManager { public: typedef size_t TicketType; - typedef typename LinearMap::iterator iterator; - - ObserversManager ( void ) = default; - ~ObserversManager ( void ) noexcept = default; - - TicketType Add ( T parObserver ); - void Remove ( TicketType parTicket ) noexcept; - void Update ( TicketType parTicket, T parObserver ); - std::size_t size ( void ) const { return m_list.size(); } - iterator begin ( void ) { return m_list.begin(); } - iterator end ( void ) { return m_list.end(); } private: - LinearMap m_list; + struct TicketedWrapper { + TicketedWrapper ( void ) = default; + TicketedWrapper ( T parItem, TicketType parTicket ) : + itm(parItem), + ticket(parTicket) + { + } + + T itm; + TicketType ticket; + + bool operator== ( const TicketedWrapper& parOther ) const { return parOther.ticket == ticket; } + bool operator== ( TicketType parOther ) const { return parOther == ticket; } + }; + static T& TicketedWrapperToItm ( TicketedWrapper& parWrapper ) { return parWrapper.itm; } + + typedef tree TreeType; + typedef typename tree::iterator TreeIteratorType; + + public: + enum { + Ticket_Null = 0 + }; + typedef boost::transform_iterator, TreeIteratorType> iterator; + + ObserversManager ( void ); + ~ObserversManager ( void ) noexcept = default; + + TicketType Add ( T parObserver, TicketType parParent=Ticket_Null ); + void Remove ( TicketType parTicket ) noexcept; + void Update ( TicketType parTicket, T parObserver ); + std::size_t size ( void ) const { return m_tree.size(); } + iterator begin ( void ) { return iterator(m_tree.begin(), &TicketedWrapperToItm); } + iterator end ( void ) { return iterator(m_tree.end(), &TicketedWrapperToItm); } + + private: + TreeIteratorType GetByTicket_AssertPresent ( TicketType parTicket ); + + TreeType m_tree; + TicketType m_nextTicket; }; ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template - typename ObserversManager::TicketType ObserversManager::Add (T parObserver) { - m_list.push_back(parObserver); - return static_cast(m_list.size()); + ObserversManager::ObserversManager() : + m_nextTicket(1) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename ObserversManager::TicketType ObserversManager::Add (T parObserver, TicketType parParent) { + const auto currTicket = m_nextTicket; + if (Ticket_Null == parParent) + m_tree.insert(m_tree.begin(), TicketedWrapper(parObserver, currTicket)); + else + m_tree.append_child(GetByTicket_AssertPresent(parParent), TicketedWrapper(parObserver, currTicket)); + + ++m_nextTicket; + return currTicket; } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template void ObserversManager::Remove (TicketType parTicket) noexcept { - m_list.erase_absolute(parTicket - 1); + auto deleme = GetByTicket_AssertPresent(parTicket); + m_tree.erase(deleme); + if (parTicket == m_nextTicket - 1) + --m_nextTicket; } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template void ObserversManager::Update (TicketType parTicket, T parObserver) { - std::swap(*m_list.at_absolute(parTicket - 1), parObserver); + std::swap(GetByTicket_AssertPresent(parTicket)->itm, parObserver); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename ObserversManager::TreeIteratorType ObserversManager::GetByTicket_AssertPresent (TicketType parTicket) { + auto ret = std::find(m_tree.begin(), m_tree.end(), parTicket); + assert(m_tree.end() != ret); + return ret; } } //namespace cloonel