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
|
#ifndef idF5E41734950640CDA3C949E0D3A9A30D
|
||||||
#define idF5E41734950640CDA3C949E0D3A9A30D
|
#define idF5E41734950640CDA3C949E0D3A9A30D
|
||||||
|
|
||||||
#include "linearmap.hpp"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
|
#include <tree.hh>
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
|
|
||||||
namespace cloonel {
|
namespace cloonel {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ObserversManager {
|
class ObserversManager {
|
||||||
public:
|
public:
|
||||||
typedef size_t TicketType;
|
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:
|
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>
|
template <typename T>
|
||||||
typename ObserversManager<T>::TicketType ObserversManager<T>::Add (T parObserver) {
|
ObserversManager<T>::ObserversManager() :
|
||||||
m_list.push_back(parObserver);
|
m_nextTicket(1)
|
||||||
return static_cast<TicketType>(m_list.size());
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
///--------------------------------------------------------------------------
|
||||||
|
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>
|
template <typename T>
|
||||||
void ObserversManager<T>::Remove (TicketType parTicket) noexcept {
|
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>
|
template <typename T>
|
||||||
void ObserversManager<T>::Update (TicketType parTicket, T parObserver) {
|
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
|
} //namespace cloonel
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue