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.
This commit is contained in:
King_DuckZ 2014-07-06 22:00:51 +02:00
parent ad613dc3fd
commit 1682b1ade7

View file

@ -20,54 +20,109 @@
#ifndef idF5E41734950640CDA3C949E0D3A9A30D
#define idF5E41734950640CDA3C949E0D3A9A30D
#include "linearmap.hpp"
#include <cassert>
#include <vector>
#include <algorithm>
#include <iterator>
#include <ciso646>
#include <tree.hh>
#include <boost/iterator/transform_iterator.hpp>
namespace cloonel {
template <typename T>
class ObserversManager {
public:
typedef size_t TicketType;
typedef typename LinearMap<T>::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<T> 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<TicketedWrapper> TreeType;
typedef typename tree<TicketedWrapper>::iterator TreeIteratorType;
public:
enum {
Ticket_Null = 0
};
typedef boost::transform_iterator<std::function<T&(TicketedWrapper&)>, 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 T>
typename ObserversManager<T>::TicketType ObserversManager<T>::Add (T parObserver) {
m_list.push_back(parObserver);
return static_cast<TicketType>(m_list.size());
ObserversManager<T>::ObserversManager() :
m_nextTicket(1)
{
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <typename T>
typename ObserversManager<T>::TicketType ObserversManager<T>::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 <typename T>
void ObserversManager<T>::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 <typename T>
void ObserversManager<T>::Update (TicketType parTicket, T parObserver) {
std::swap(*m_list.at_absolute(parTicket - 1), parObserver);
std::swap(GetByTicket_AssertPresent(parTicket)->itm, parObserver);
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <typename T>
typename ObserversManager<T>::TreeIteratorType ObserversManager<T>::GetByTicket_AssertPresent (TicketType parTicket) {
auto ret = std::find(m_tree.begin(), m_tree.end(), parTicket);
assert(m_tree.end() != ret);
return ret;
}
} //namespace cloonel