From b4ddfa8f4f5c2b4ec34829aae9aeafabab9d17bd Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sun, 6 Jul 2014 02:21:25 +0200 Subject: [PATCH] Fix for a crash occurring when the window is resized. Temporary Platform objects were registering themselves. The move ctor would then initialize the final object in the circular buffer (see PlatformSystem), but it would leave the address of the temporary object registered in the ObserversManager. --- src/observersmanager.hpp | 13 +++++++++++++ src/sdlmain.cpp | 6 ++++++ src/sdlmain.hpp | 1 + src/sizenotifiable.cpp | 4 +++- src/sizenotifiable.hpp | 8 ++++---- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/observersmanager.hpp b/src/observersmanager.hpp index 680c571..6a9d657 100644 --- a/src/observersmanager.hpp +++ b/src/observersmanager.hpp @@ -96,6 +96,7 @@ namespace cloonel { 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); } @@ -148,6 +149,18 @@ namespace cloonel { m_list.resize(newSize); } } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + 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); + } } //namespace cloonel #endif diff --git a/src/sdlmain.cpp b/src/sdlmain.cpp index eaa6ae7..44c0d52 100644 --- a/src/sdlmain.cpp +++ b/src/sdlmain.cpp @@ -140,6 +140,12 @@ namespace cloonel { m_localData->resChangeNotifList.Remove(parID); } + ///------------------------------------------------------------------------ + ///------------------------------------------------------------------------ + void SDLMain::SwapRegisteredForResChange (size_t parID, SizeNotifiableBase* parNotif) { + m_localData->resChangeNotifList.Update(parID, parNotif); + } + ///------------------------------------------------------------------------ ///------------------------------------------------------------------------ ushort2 SDLMain::WidthHeight() const noexcept { diff --git a/src/sdlmain.hpp b/src/sdlmain.hpp index bbdd7b6..74e8ffd 100644 --- a/src/sdlmain.hpp +++ b/src/sdlmain.hpp @@ -41,6 +41,7 @@ namespace cloonel { void SetResolution ( ushort2 parRes ); size_t RegisterForResChange ( SizeNotifiableBase* parNotif ); void UnregisterForResChange ( size_t parID ) noexcept; + void SwapRegisteredForResChange ( size_t parID, SizeNotifiableBase* parNotif ); private: struct LocalData; diff --git a/src/sizenotifiable.cpp b/src/sizenotifiable.cpp index 3bba401..ac08df8 100644 --- a/src/sizenotifiable.cpp +++ b/src/sizenotifiable.cpp @@ -34,7 +34,7 @@ namespace cloonel { ///---------------------------------------------------------------------- ///---------------------------------------------------------------------- - AutoRegister::AutoRegister (AutoRegister&& parOther) : + AutoRegister::AutoRegister (AutoRegister&& parOther, SizeNotifiableBase* parSwapTo) : m_sdlmain(nullptr), m_id(0) #if !defined(NDEBUG) @@ -46,6 +46,8 @@ namespace cloonel { #if !defined(NDEBUG) std::swap(m_registered, parOther.m_registered); #endif + assert(m_sdlmain); + m_sdlmain->SwapRegisteredForResChange(m_id, parSwapTo); } } //namespace regbehaviours diff --git a/src/sizenotifiable.hpp b/src/sizenotifiable.hpp index 8249bdc..132cf34 100644 --- a/src/sizenotifiable.hpp +++ b/src/sizenotifiable.hpp @@ -35,7 +35,7 @@ namespace cloonel { enum { SDLMAIN_NEEDED = false }; DontRegister ( void ) = default; - DontRegister ( DontRegister&& ) { } + DontRegister ( DontRegister&&, SizeNotifiableBase* ) { } ~DontRegister ( void ) noexcept = default; void Register ( SizeNotifiableBase* ) const noexcept { return; } @@ -46,7 +46,7 @@ namespace cloonel { public: enum { SDLMAIN_NEEDED = true }; - AutoRegister ( AutoRegister&& parOther ); + AutoRegister ( AutoRegister&& parOther, SizeNotifiableBase* parSwapTo ); explicit AutoRegister ( SDLMain* parMain ) : m_sdlmain(parMain) #if !defined(NDEBUG) @@ -92,7 +92,7 @@ namespace cloonel { public: SizeNotifiable ( const SizeNotifiable& ) = delete; SizeNotifiable ( SizeNotifiable&& parOther ) : - RegisterBehaviour(parOther), + RegisterBehaviour(std::move(parOther), this), SizeNotifiableBase(parOther) { } @@ -110,7 +110,7 @@ namespace cloonel { public: SizeNotifiable ( const SizeNotifiable& ) = delete; SizeNotifiable ( SizeNotifiable&& parOther ) : - RegisterBehaviour(std::move(parOther)), + RegisterBehaviour(std::move(parOther), this), SizeNotifiableBase(parOther) { }