1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-22 23:48:02 +02:00

Back-pointer from Track to TrackList is weak (fixes crashes)

This commit is contained in:
Paul Licameli 2017-07-10 11:48:11 -04:00
parent 9489fed04e
commit 16645f6b95
3 changed files with 61 additions and 42 deletions

View File

@ -922,6 +922,8 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mbLoadedFromAup( false ) mbLoadedFromAup( false )
{ {
mTracks->SetSelf(mTracks);
#ifdef EXPERIMENTAL_DA2 #ifdef EXPERIMENTAL_DA2
SetBackgroundColour(theTheme.Colour( clrMedium )); SetBackgroundColour(theTheme.Colour( clrMedium ));
#endif #endif

View File

@ -48,7 +48,6 @@ Track::Track(const std::shared_ptr<DirManager> &projDirManager)
: vrulerSize(36,0), : vrulerSize(36,0),
mDirManager(projDirManager) mDirManager(projDirManager)
{ {
mList = NULL;
mSelected = false; mSelected = false;
mLinked = false; mLinked = false;
@ -72,7 +71,6 @@ Track::Track(const std::shared_ptr<DirManager> &projDirManager)
Track::Track(const Track &orig) Track::Track(const Track &orig)
: vrulerSize( orig.vrulerSize ) : vrulerSize( orig.vrulerSize )
{ {
mList = NULL;
mY = 0; mY = 0;
mIndex = 0; mIndex = 0;
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY #ifdef EXPERIMENTAL_OUTPUT_DISPLAY
@ -119,11 +117,12 @@ Track::~Track()
TrackNodePointer Track::GetNode() const TrackNodePointer Track::GetNode() const
{ {
wxASSERT(mList == NULL || this == mNode->get()); wxASSERT(mList.lock() == NULL || this == mNode->get());
return mNode; return mNode;
} }
void Track::SetOwner(TrackList *list, TrackNodePointer node) void Track::SetOwner
(const std::weak_ptr<TrackList> &list, TrackNodePointer node)
{ {
mList = list; mList = list;
mNode = node; mNode = node;
@ -207,9 +206,10 @@ int Track::GetHeight() const
void Track::SetHeight(int h) void Track::SetHeight(int h)
{ {
mHeight = h; mHeight = h;
if (mList) { auto pList = mList.lock();
mList->RecalcPositions(mNode); if (pList) {
mList->ResizingEvent(mNode); pList->RecalcPositions(mNode);
pList->ResizingEvent(mNode);
} }
} }
#endif // EXPERIMENTAL_OUTPUT_DISPLAY #endif // EXPERIMENTAL_OUTPUT_DISPLAY
@ -221,37 +221,40 @@ bool Track::GetMinimized() const
void Track::SetMinimized(bool isMinimized) void Track::SetMinimized(bool isMinimized)
{ {
auto pList = mList.lock();
mMinimized = isMinimized; mMinimized = isMinimized;
if (mList) { if (pList) {
mList->RecalcPositions(mNode); pList->RecalcPositions(mNode);
mList->ResizingEvent(mNode); pList->ResizingEvent(mNode);
} }
} }
void Track::SetLinked(bool l) void Track::SetLinked(bool l)
{ {
auto pList = mList.lock();
mLinked = l; mLinked = l;
if (mList) { if (pList) {
mList->RecalcPositions(mNode); pList->RecalcPositions(mNode);
mList->ResizingEvent(mNode); pList->ResizingEvent(mNode);
} }
} }
Track *Track::GetLink() const Track *Track::GetLink() const
{ {
if (!mList) auto pList = mList.lock();
if (!pList)
return nullptr; return nullptr;
if (!mList->isNull(mNode)) { if (!pList->isNull(mNode)) {
if (mLinked) { if (mLinked) {
auto next = mNode; auto next = mNode;
++next; ++next;
if (!mList->isNull(next)) { if (!pList->isNull(next)) {
return next->get(); return next->get();
} }
} }
if (mList->hasPrev(mNode)) { if (pList->hasPrev(mNode)) {
auto prev = mNode; auto prev = mNode;
--prev; --prev;
auto track = prev->get(); auto track = prev->get();
@ -282,7 +285,8 @@ bool Track::IsSyncLockSelected() const
if (!p || !p->IsSyncLocked()) if (!p || !p->IsSyncLocked())
return false; return false;
SyncLockedTracksIterator git(mList); auto pList = mList.lock();
SyncLockedTracksIterator git(pList.get());
Track *t = git.StartWith(const_cast<Track*>(this)); Track *t = git.StartWith(const_cast<Track*>(this));
if (!t) { if (!t) {
@ -384,7 +388,7 @@ Track *TrackListIterator::StartWith(Track * val)
return NULL; return NULL;
} }
if (val->mList == NULL) if (val->mList.lock() == NULL)
return nullptr; return nullptr;
cur = val->GetNode(); cur = val->GetNode();
@ -790,9 +794,9 @@ void TrackList::Swap(TrackList &that)
{ {
ListOfTracks::swap(that); ListOfTracks::swap(that);
for (auto it = begin(), last = end(); it != last; ++it) for (auto it = begin(), last = end(); it != last; ++it)
(*it)->SetOwner(this, it); (*it)->SetOwner(this->mSelf, it);
for (auto it = that.begin(), last = that.end(); it != last; ++it) for (auto it = that.begin(), last = that.end(); it != last; ++it)
(*it)->SetOwner(&that, it); (*it)->SetOwner(that.mSelf, it);
} }
TrackList::~TrackList() TrackList::~TrackList()
@ -886,7 +890,7 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
value_type track = std::move(*iter); value_type track = std::move(*iter);
erase(iter); erase(iter);
Track *pTrack = track.get(); Track *pTrack = track.get();
pTrack->SetOwner(this, insert(end(), std::move(track))); pTrack->SetOwner(mSelf, insert(end(), std::move(track)));
} }
auto n = begin(); auto n = begin();
RecalcPositions(n); RecalcPositions(n);
@ -900,7 +904,7 @@ Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
push_back(value_type(pTrack = t.release())); push_back(value_type(pTrack = t.release()));
auto n = end(); auto n = end();
--n; --n;
pTrack->SetOwner(this, n); pTrack->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
return back().get(); return back().get();
@ -921,7 +925,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
Track *pTrack; Track *pTrack;
push_front(value_type(pTrack = t.release())); push_front(value_type(pTrack = t.release()));
auto n = begin(); auto n = begin();
pTrack->SetOwner(this, n); pTrack->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
return front().get(); return front().get();
@ -936,7 +940,7 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
push_back(t); push_back(t);
auto n = end(); auto n = end();
--n; --n;
t->SetOwner(this, n); t->SetOwner(mSelf, n);
RecalcPositions(n); RecalcPositions(n);
ResizingEvent(n); ResizingEvent(n);
return back().get(); return back().get();
@ -951,13 +955,13 @@ auto TrackList::Replace(Track * t, value_type &&with) -> value_type
value_type holder; value_type holder;
if (t && with) { if (t && with) {
auto node = t->GetNode(); auto node = t->GetNode();
t->SetOwner(nullptr, {}); t->SetOwner({}, {});
holder = std::move(*node); holder = std::move(*node);
Track *pTrack = with.get(); Track *pTrack = with.get();
*node = std::move(with); *node = std::move(with);
pTrack->SetOwner(this, node); pTrack->SetOwner(mSelf, node);
RecalcPositions(node); RecalcPositions(node);
DeletionEvent(); DeletionEvent();
@ -971,7 +975,7 @@ TrackNodePointer TrackList::Remove(Track *t)
TrackNodePointer result(end()); TrackNodePointer result(end());
if (t) { if (t) {
auto node = t->GetNode(); auto node = t->GetNode();
t->SetOwner(nullptr, {}); t->SetOwner({}, {});
if (!isNull(node)) { if (!isNull(node)) {
value_type holder = std::move( *node ); value_type holder = std::move( *node );
@ -1152,12 +1156,12 @@ void TrackList::SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
// Reinsert them // Reinsert them
Track *pTrack; Track *pTrack;
if (save22) if (save22)
pTrack = save22.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save22))); pTrack = save22.get(), pTrack->SetOwner(mSelf, s1 = insert(s1, std::move(save22)));
pTrack = save21.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save21))); pTrack = save21.get(), pTrack->SetOwner(mSelf, s1 = insert(s1, std::move(save21)));
if (save12) if (save12)
pTrack = save12.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save12))); pTrack = save12.get(), pTrack->SetOwner(mSelf, s2 = insert(s2, std::move(save12)));
pTrack = save11.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save11))); pTrack = save11.get(), pTrack->SetOwner(mSelf, s2 = insert(s2, std::move(save11)));
// Now correct the Index in the tracks, and other things // Now correct the Index in the tracks, and other things
RecalcPositions(s1); RecalcPositions(s1);

View File

@ -91,7 +91,7 @@ class AUDACITY_DLL_API Track /* not final */
// To be TrackDisplay // To be TrackDisplay
protected: protected:
TrackList *mList; std::weak_ptr<TrackList> mList;
TrackNodePointer mNode{}; TrackNodePointer mNode{};
int mIndex; int mIndex;
int mY; int mY;
@ -113,22 +113,28 @@ class AUDACITY_DLL_API Track /* not final */
public: public:
// Given a bare pointer, find a shared_ptr. But this is not possible for // Given a bare pointer, find a shared_ptr. But this is not possible for
// a track not owned by any list, so the result can be null. // a track not owned by any project, so the result can be null.
template<typename Subclass = Track> template<typename Subclass = Track>
inline static std::shared_ptr<Subclass> Pointer( Track *t ) inline static std::shared_ptr<Subclass> Pointer( Track *t )
{ {
if (t && t->mList) if (t) {
return std::static_pointer_cast<Subclass>(*t->mNode); auto pList = t->mList.lock();
if (pList)
return std::static_pointer_cast<Subclass>(*t->mNode);
}
return {}; return {};
} }
template<typename Subclass = const Track> template<typename Subclass = const Track>
inline static std::shared_ptr<Subclass> Pointer( const Track *t ) inline static std::shared_ptr<Subclass> Pointer( const Track *t )
{ {
if (t && t->mList) { if (t) {
std::shared_ptr<const Track> p{ *t->mNode }; auto pList = t->mList.lock();
// Let you change the type, but not cast away the const if (pList) {
return std::static_pointer_cast<Subclass>(p); std::shared_ptr<const Track> p{ *t->mNode };
// Let you change the type, but not cast away the const
return std::static_pointer_cast<Subclass>(p);
}
} }
return {}; return {};
} }
@ -192,7 +198,8 @@ class AUDACITY_DLL_API Track /* not final */
private: private:
TrackNodePointer GetNode() const; TrackNodePointer GetNode() const;
void SetOwner(TrackList *list, TrackNodePointer node); void SetOwner
(const std::weak_ptr<TrackList> &list, TrackNodePointer node);
// Keep in Track // Keep in Track
@ -542,6 +549,9 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
// Move is defined in terms of Swap // Move is defined in terms of Swap
void Swap(TrackList &that); void Swap(TrackList &that);
void SetSelf( const std::shared_ptr<TrackList> &self )
{ mSelf = self; }
// Destructor // Destructor
virtual ~TrackList(); virtual ~TrackList();
@ -618,7 +628,8 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack) std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
{ {
auto pTrack = wTrack.lock(); auto pTrack = wTrack.lock();
if (pTrack && this == pTrack->mList) auto pList = pTrack->mList.lock();
if (pTrack && this == pList.get())
return pTrack; return pTrack;
return {}; return {};
} }
@ -654,6 +665,8 @@ private:
void ResizingEvent(TrackNodePointer node); void ResizingEvent(TrackNodePointer node);
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2); void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
std::weak_ptr<TrackList> mSelf;
}; };
class AUDACITY_DLL_API TrackFactory class AUDACITY_DLL_API TrackFactory