From 103689a29aa62fd32f93f1127958005b6e929091 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 6 Jul 2014 20:50:00 +0200 Subject: [PATCH] Refactoring in ObserversManager. Pull out the storage part so the class is more tidy. --- src/linearmap.hpp | 195 +++++++++++++++++++++++++++++++++++++++ src/observersmanager.hpp | 110 ++-------------------- 2 files changed, 204 insertions(+), 101 deletions(-) create mode 100644 src/linearmap.hpp diff --git a/src/linearmap.hpp b/src/linearmap.hpp new file mode 100644 index 0000000..0c8e5e8 --- /dev/null +++ b/src/linearmap.hpp @@ -0,0 +1,195 @@ +/* + Copyright 2014 Michele "King_DuckZ" Santullo + + This file is part of CloonelJump. + + CloonelJump is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CloonelJump is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CloonelJump. If not, see . +*/ + +#ifndef idEA67296D7EC847B58BB3D52DBC9E51BA +#define idEA67296D7EC847B58BB3D52DBC9E51BA + +#include +#include +#include +#include +#include +#include + +namespace cloonel { + namespace implem { + template + class LinearMapIterator : public boost::iterator_facade, typename std::iterator_traits::value_type, typename std::iterator_traits::iterator_category, typename std::iterator_traits::reference, typename std::iterator_traits::difference_type> { + + typedef boost::iterator_facade, typename std::iterator_traits::value_type, typename std::iterator_traits::iterator_category, typename std::iterator_traits::reference, typename std::iterator_traits::difference_type> parent_type; + + typedef typename parent_type::reference reference; + typedef typename parent_type::value_type value_type; + typedef S size_type; + public: + LinearMapIterator ( I parItemsStart, I parItemsEnd, std::vector::const_iterator parOccupiedStart ) : + m_itStart(parItemsStart), + m_itEnd(parItemsEnd), + m_itOccupied(parOccupiedStart) + { + } + ~LinearMapIterator ( void ) noexcept = default; + + private: + friend class boost::iterator_core_access; + + void increment ( void ) { + do { + ++m_itStart; + ++m_itOccupied; + } while (m_itEnd != m_itStart and not *m_itOccupied); + } + bool equal ( const LinearMapIterator& parOther ) const { + return m_itStart == parOther.m_itStart; + } + reference dereference ( void ) const { + return *m_itStart; + } + void advance ( size_type parAdv ) { + while (parAdv and m_itEnd != m_itStart) { + increment(); + --parAdv; + } + } + + I m_itStart; + const I m_itEnd; + std::vector::const_iterator m_itOccupied; + }; + } //namespace implem + + template > + class LinearMap { + public: + typedef size_t size_type; + typedef T value_type; + typedef typename implem::LinearMapIterator iterator; + typedef typename implem::LinearMapIterator const_iterator; + + LinearMap ( void ) = default; + LinearMap ( LinearMap&& parOther ); + ~LinearMap ( void ) noexcept = default; + + size_type size ( void ) const { return m_usedCount; } + size_type max_size ( void ) const noexcept { return m_list.max_size(); } + size_type capacity ( void ) const noexcept { return m_list.capacity(); } + void shrink_to_fit ( void ); + bool empty ( void ) const noexcept { return m_list.empty(); } + void push_back ( const value_type& parNew ); + void push_back ( value_type&& parNew ); + void swap ( LinearMap& parOther ); + void clear ( void ); + iterator erase_absolute ( size_type parIndex ); + iterator at_absolute ( size_type parIndex ); + + iterator begin ( void ) { return iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); } + iterator end ( void ) { return iterator(m_list.end(), m_list.end(), m_occupied.cend()); } + const_iterator begin ( void ) const { return const_iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); } + const_iterator end ( void ) const { return const_iterator(m_list.end(), m_list.end(), m_occupied.cend()); } + const_iterator cbegin ( void ) const { return const_iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); } + const_iterator cend ( void ) const { return const_iterator(m_list.end(), m_list.end(), m_occupied.cend()); } + + private: + Container m_list; + std::vector m_occupied; + size_type m_usedCount; + }; + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void LinearMap::shrink_to_fit() { + m_list.shrink_to_fit(); + m_occupied.shrink_to_fit(); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void LinearMap::push_back (const value_type& parNew) { + m_list.push_back(parNew); + m_occupied.push_back(true); + ++m_usedCount; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void LinearMap::push_back (value_type&& parNew) { + m_list.push_back(std::move(parNew)); + m_occupied.push_back(true); + ++m_usedCount; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void LinearMap::swap (LinearMap& parOther) { + m_list.swap(parOther.m_list); + m_occupied.swap(parOther.m_occupied); + std::swap(m_usedCount, parOther.m_usedCount); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + void LinearMap::clear() { + m_list.clear(); + m_occupied.clear(); + m_usedCount = 0; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename LinearMap::iterator LinearMap::erase_absolute (size_type parIndex) { + auto ret = at_absolute(parIndex); + ++ret; + + m_occupied[parIndex] = false; + --m_usedCount; + + size_type deleCount = 0; + for (auto itOcc = m_occupied.rbegin(), itOccEND = m_occupied.rend(); itOcc != itOccEND and not *itOcc; ++itOcc) { + ++deleCount; + } + + if (deleCount) { + assert(deleCount <= m_occupied.size()); + const auto newSize = m_occupied.size() - deleCount; + m_occupied.resize(newSize); + m_list.resize(newSize); + } + return ret; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + template + typename LinearMap::iterator LinearMap::at_absolute (size_type parIndex) { + assert(m_usedCount > 0); + assert(m_list.size() == m_occupied.size()); + assert(parIndex < m_list.size()); + assert(m_occupied[parIndex]); + + return begin() + std::count_if(m_occupied.begin(), m_occupied.begin() + parIndex, [] (bool a) { return a; }); + } +} //namespace cloonel + +#endif diff --git a/src/observersmanager.hpp b/src/observersmanager.hpp index 6a9d657..40d08f3 100644 --- a/src/observersmanager.hpp +++ b/src/observersmanager.hpp @@ -20,6 +20,7 @@ #ifndef idF5E41734950640CDA3C949E0D3A9A30D #define idF5E41734950640CDA3C949E0D3A9A30D +#include "linearmap.hpp" #include #include #include @@ -27,101 +28,31 @@ #include namespace cloonel { - namespace implem { - template - class Iterator { - public: - Iterator ( const std::vector& parOccupied, std::vector& parItems, bool parEnd ) : - m_occupied(parOccupied), - m_items(parItems), - m_pos(parEnd ? m_occupied.size() : 0) - { - assert(m_occupied.size() == m_items.size()); - } - Iterator ( const Iterator& parOther ) : - m_occupied(parOther.m_occupied), - m_items(parOther.m_items), - m_pos(parOther.m_pos) - { - } - ~Iterator ( void ) noexcept = default; - - T operator-> ( void ) { - assert(m_pos < m_occupied.size()); - assert(m_occupied[m_pos]); - return m_items[m_pos]; - } - T operator* ( void ) { - assert(m_pos < m_occupied.size()); - assert(m_occupied[m_pos]); - return m_items[m_pos]; - } - - Iterator& operator++ ( void ) { - if (m_occupied.size() == m_pos) - return *this; - auto itNext = std::find(m_occupied.begin() + static_cast::difference_type>(m_pos + 1), m_occupied.end(), true); - if (m_occupied.end() != itNext) - m_pos = static_cast(itNext - m_occupied.begin()); - else - m_pos = m_occupied.size(); - return *this; - } - Iterator operator++ ( int ) { - Iterator prevState(*this); - ++(*this); - return prevState; - } - - bool operator== ( const Iterator& parOther ) const { - return m_pos == parOther.m_pos and &m_items == &parOther.m_items; - } - bool operator!= ( const Iterator& parOther ) const { return not this->operator==(parOther); } - - private: - const std::vector& m_occupied; - std::vector& m_items; - std::size_t m_pos; - }; - } //namespace implem - template class ObserversManager { public: typedef size_t TicketType; - typedef implem::Iterator iterator; + typedef typename LinearMap::iterator iterator; - ObserversManager ( void ); + 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_usedCount; } - iterator begin ( void ) { return iterator(m_occupied, m_list, false); } - iterator end ( void ) { return iterator(m_occupied, m_list, true); } + 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: - std::vector m_list; - std::vector m_occupied; - std::size_t m_usedCount; + LinearMap m_list; }; - ///-------------------------------------------------------------------------- - ///-------------------------------------------------------------------------- - template - ObserversManager::ObserversManager() : - m_usedCount(0) - { - } - ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template typename ObserversManager::TicketType ObserversManager::Add (T parObserver) { m_list.push_back(parObserver); - m_occupied.push_back(true); - ++m_usedCount; return static_cast(m_list.size()); } @@ -129,37 +60,14 @@ namespace cloonel { ///-------------------------------------------------------------------------- template void ObserversManager::Remove (TicketType parTicket) noexcept { - assert(static_cast(parTicket) <= m_list.size()); - assert(m_occupied[parTicket - 1]); - assert(m_usedCount > 0); - assert(m_list.size() == m_occupied.size()); - - m_occupied[parTicket - 1] = false; - --m_usedCount; - - std::size_t deleCount = 0; - for (auto itOcc = m_occupied.rbegin(), itOccEND = m_occupied.rend(); itOcc != itOccEND and not *itOcc; ++itOcc) { - ++deleCount; - } - - if (deleCount) { - assert(deleCount <= m_occupied.size()); - const std::size_t newSize = m_occupied.size() - deleCount; - m_occupied.resize(newSize); - m_list.resize(newSize); - } + m_list.erase_absolute(parTicket - 1); } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- template void ObserversManager::Update (TicketType parTicket, T parObserver) { - assert(static_cast(parTicket) <= m_list.size()); - assert(m_occupied[parTicket - 1]); - assert(m_usedCount > 0); - assert(m_list.size() == m_occupied.size()); - - std::swap(m_list[parTicket - 1], parObserver); + std::swap(*m_list.at_absolute(parTicket - 1), parObserver); } } //namespace cloonel