-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve creational correctness involving tracks and clips #7594
base: master
Are you sure you want to change the base?
Improve creational correctness involving tracks and clips #7594
Conversation
To simplify the Track constructor and loosen the coupling between specific Track types and the base Track class
If there is contention, where one thread wants to do something with the track and the other is trying to destroy it, we are betting that the destructor will win over the lock last, which wont always happen. The real fix in this instance is to ensure that when the destructor is called, the object is no longer in use by anything else. By removing the lock, this isn't undoing a problem. The problem was always still there. The lock will only help 50% of the time (i.e., in the scenario mentioned above), with the other 50% crashing the program. The chances get slimmer as the contention increases, but this doesn't change the fact that this is still error-prone.
We can keep things simple and use the signal already provided by Qt when destroying QObject's.
Same with destroyedTrack, we can use the destroyed signal that Qt provides us to make things simpler.
No need for a function call.
QueuedConnections were used previously. Because this kind of connection only invokes the slot when Qt returns to the event loop, this could be a problem if the track or clip was deleted in between the time when the signal that a track or clip was added was emitted, and when the slot to add the corresponding track or clip view was invoked. An alternative solution that could be even better overall is to use weak pointers in the view classes and manage the objects using shared pointers. This is a more involved task, however.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few thoughts. Another doubt I have is that, does this fix that crash with deleting a track while playing?
I believe crashes like those happen because of synchronization issues involving mutexes (which I believe should be fixed, albeit not ideally). What I am addressing here with this PR is the problem where we are adding clips to tracks and tracks to track containers (like the song editor) way too early. If I created a |
Wait, nevermind, whatever |
…om it This behavior of removing the child from its parent in the child's destructor can be removed once we start using smart pointers.
@@ -98,35 +88,34 @@ Track::~Track() | |||
* \param tt The type of track to create |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you should change these 2 parameters here too.
Currently, we add tracks and clips prematurely to there respective containers, i.e., they are added within the base class. This has seemed to have caused a number of problems involving calls to pure virtual functions (because the object wasn't fully created yet), to
dynamic_cast
failures and ultimately crashes. This PR fixes this by only adding a track or clip to their respective containers after the object has been fully constructed.There are also fixes that address potential issues that can happen when creating the corresponding view for a track or clip. What happens is that currently, we use
Qt::QueuedConnection
when signaling that the view should be made after the object was created. However, this gives a deadly grace period where in between those two events, the object could be deleted before Qt returns to the event loop and creates the view. To fix this, we useQt::DirectConnection
instead, which eliminates this grace period. Removing tracks and clips still must useQt::QueuedConnection
(which they currently do) orQObject::deleteLater
since Qt could be using the view during that time.In addition, I added some minor refactoring improvements like loosening the coupling between specific track types and the base track class by moving the type information outside
Track
and makingTrack::type
pure virtual. This improvement could not be moved into another PR because callers currently callTrack::type
before the track is fully created.Also moved specific pattern clip/pattern store functionality into Qt signals within
PatternStore
.The change to moving to smart pointers is involved and will pollute this PR. I'm moving the improvement of ownership semantics to another PR after this one is merged. This one is focusing on making sure objects are fully initialized before adding them to their parents.