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:
parent
ad613dc3fd
commit
1682b1ade7
1 changed files with 73 additions and 18 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue