-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
remove ConstLegacyControllerMappingVisitor #3636
remove ConstLegacyControllerMappingVisitor #3636
Conversation
This class increased coupling and made the code very confusing.
a7a93a5
to
80f141c
Compare
@@ -13,8 +12,11 @@ class LegacyHidControllerMapping : public LegacyControllerMapping { | |||
~LegacyHidControllerMapping() override { | |||
} | |||
|
|||
LegacyControllerMapping* clone() const override { |
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.
Consistently use LegacyControllerMappingPointer
everywhere, not plain pointers. Your code already has memory leaks.
Change the typedef from QSharedPointer to std::shared_pointer and then you could use dynamic_pointer_cast
instead of dynamic_cast
.
http://www.cplusplus.com/reference/memory/dynamic_pointer_cast/
Alternatively use qSharedPointerDynamicCast
but I would prefer the standard C++ route instead of dealing with custom Qt re-inventions if not strictly necessary.
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.
I'll get rid of the QSharedPointer and use std. Might make the diff quite big though.
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.
If the diff is too large then keep using QSharedPointer. Doesn't really matter.
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.
Come to think of it, std::unique_ptr might be a better choice here to help enforce that the cloned object is not shared between threads.
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.
Ugh, there's no equivalent of dynamic_pointer_cast
for unique_ptr...
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 add a comment: // Downcast and take ownership on success
It's a shame that you need to write so much code and a comment to get this right. C++ 😩
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.
🙈
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.
Actually, a shared pointer is needed. DlgPrefController, ControllerInputMappingTableModel, and ControllerOutputMappingTableModel all share a pointer in the main thread.
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.
void HidController::setMapping(std::unique_ptr<LegacyControllerMapping> pMapping) {
m_pMapping = std::unique_ptr<LegacyHidControllerMapping>(
dynamic_cast<LegacyHidControllerMapping*>(pMapping.get()));
if (m_pMapping) {
pMapping.release();
}
}
This seems to double free or something? Forget it, I'll use shared pointers and DEBUG_ASSERT that use_count is 1. 🙈
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.
Exactly oncy. It is freed later by m_pMapping
if the dynamic_cast succeeded or immediately when pMapping
goes out of scope. release() doesn't free.
I gave up trying to mix shared_ptr and unique_ptr. The best I could do was DEBUG_ASSERT that shared_ptr's use_count is 1. That took way more work than it should have. |
0b2e4cf
to
fd670fe
Compare
This happens if you use the wrong abstractions like a shared pointer for everything because it is convenient without thinking about ownership and the consequences. This design was already broken before and don't need to be fixed right now. |
b59e84b
to
44f0168
Compare
src/controllers/controller.h
Outdated
// LegacyControllerMapping. | ||
// Trying to cast a std::shared_ptr to a std::unique_ptr is not worth the trouble. | ||
// The use_count is 2 at this point, one use by the caller and one use by this class. | ||
VERIFY_OR_DEBUG_ASSERT(pMapping.use_count() == 2) { |
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.
had to change this to 2 because C++
wtf is this language 🙃
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.
If you pass it with std::move
it should (or might?) work as expected. This is what you would also need to do when using a std::unique_ptr.
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.
Explicitly enforce the move on the caller site by turning the parameter type into an rvalue reference, i.e. std::shared_ptr<..>&&
.
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.
All ugly workarounds for missing move semantics and the reason why std::unique_ptr would be a better choice for the parameter type.
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.
Casting that magic spell worked 🧙♂️
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 I could make a separate uniqueClone
method for LegacyControllerMapping? Also ugly, but 🤷
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.
Whatever, this works and CI passed. Let's move on.
44f0168
to
4efdeb5
Compare
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.
The workaround is brittle but the use count assertion ensures that we will notice early if it does not work as intended. The code before this refactoring worked more or less by chance with implicit and hidden assumptions. Thanks for taking the effort to sort this out! LGTM
Thank you for review. I think I can start decoupling the legacy mapping system from Controller and MidiController now. |
This class increased coupling and made the code very confusing.