-
Notifications
You must be signed in to change notification settings - Fork 2
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 some naked new pointers #15
Remove some naked new pointers #15
Conversation
Added make_parented in |
src/library/libraryfeature.cpp
Outdated
parented_ptr<WTrackTableView> LibraryFeature::createTableWidget(int paneId, | ||
const parented_ptr<QWidget>& parent) { | ||
auto pTrackTableView = make_parented<WTrackTableView>( | ||
parent.get(), m_pConfig, m_pTrackCollection, true); |
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 would prefer to use this interface:
parented_ptr<WTrackTableView> LibraryFeature::createTableWidget(
int paneId, QWidget* parent)
because there is no requirement that the parent for the new object is parented as well. The lifetime can be also tracked by a unique or shared pointer.
In general I prefer passing plain pointer to functions, if the function does not store the pointer.
In this case the ownership does not matter.
@uklotzde: I might remember you have posted a link to a book about that, but I cannot find it.
Is my assumption correct?
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 would primarily use parented_ptr (by value or const-ref) for return values to document the ownership. I'm not sure if this actually matters for parameters?
Possible rule: By accepting a raw pointer the called function promises not to use the pointer after returning. But passing it over to Qt for parenting a new object would violate this rule. So maybe a parented_ptr is more suitable here?
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.
Possible rule: By accepting a raw pointer the called function promises not to use the pointer after returning. But passing it over to Qt for parenting a new object would violate this rule. So maybe a parented_ptr is more suitable here?
Ok, that is one possible point of view. I originally had a different interpretation, now I am unsure.
QObject stores actually the parent pointer, but it does not own it. It is treated like a weak pointer, which is always checked against nullptr before usage.
So if we follow the rule "A raw pointer (a T*) is non-owning" it will applies to this parent pointer, and would allow to use a raw pointer parent parameter. A parented_ptr is also a non-owining pointer, but forces us to parent the passed object before passing. A raw pointer as parameter will allow to use pointers managed by shared and unique_ptrs as well.
Both solutions are good to me in this case. If we like to establish a general rule here, we have to decide if we want to force the parent pointer to have already a parent itselves.
Is this a good idea or not?
Thoughts?
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.
For me it's a good idea that a parent pointer should have a parent too, however this escalates through the LegacySkinParser
and for the moment I've stopped there. All the LegacySkinParser
should work with the parented_ptr
instead of passing raw pointers.
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.
Ok, this means we should stick with the "const parented_ptr& parent" parameter. Right?
Fine, we have a decision. :-)
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.
Yes
@@ -680,25 +679,25 @@ void BasePlaylistFeature::slotAnalyzePlaylist() { | |||
} | |||
|
|||
TreeItemModel* BasePlaylistFeature::getChildModel() { | |||
return m_childModel; | |||
return m_childModel.data(); |
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 think this should return the shared pointer here. If this is an override function, to meet an Qt interface it should be marked as override in the header file and here with a comment.
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.
Mmm it's not a Qt interface but it's our interface. We pass the TreeItemModel to a Qt interface later so returning the shared pointer implies changing the m_childModel
from all the library features. Maybe it's worth the work to prevent a break.
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.
It looks like you will inherit a lot of work, continuing this route. For me it is OK to stop here and just add the comments. I think it is OK with the strategy to first replace itching new() calls with the new concept. If we treat raw pointer as non owning pointers the code should become clear.
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r3-a-raw-pointer-a-t-is-non-owning
TrackPointer m_pSelectedTrack; | ||
|
||
QSharedPointer<TreeItemModel> m_childModel; |
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.
Use std:shared_ptr here. We have found out that it is more efficient in Qt 5.
mixxxdj#1132 (comment)
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.
Ok, fine I had my doubts in using QSharedPointer
now you've resolved them 😊
@@ -22,6 +22,7 @@ PlaylistFeature::PlaylistFeature(UserSettingsPointer pConfig, | |||
TrackCollection* pTrackCollection) | |||
: BasePlaylistFeature(pConfig, pLibrary, parent, pTrackCollection) { | |||
//construct child model | |||
m_childModel = QSharedPointer<TreeItemModel>(new TreeItemModel(this)); |
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.
Why is this shared?
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.
Is this a typo? TreeItemModel has "this" as parent.
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.
It's shared because PlaylistFeature
inherits BasePlaylistFeature
and m_childModel
is shared between the base class and the inherited class. This is because HistoryFeature
uses a HistoryTreeModel
instead of a TreeItemModel
.
And yes this is a typo, I confused it with the HistoryTreeModel
class which needs a LibraryFeature
as a constructor.
delete m_childModel; | ||
m_childModel = m_pHistoryTreeModel = new HistoryTreeModel(this, m_pTrackCollection); | ||
m_childModel = m_pHistoryTreeModel = QSharedPointer<HistoryTreeModel>( | ||
new HistoryTreeModel(this, m_pTrackCollection)); |
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.
It looks like this is also already parented.
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.
No this is not parented because HistoryTreeModel
needs the feature which is holding it to work.
@@ -7,7 +7,7 @@ class LibrarySidebarExpandedManager : public LibraryPaneManager | |||
public: | |||
LibrarySidebarExpandedManager(Library* pLibrary, QObject* parent = nullptr); | |||
|
|||
void bindPaneWidget(WBaseLibrary* sidebarWidget, | |||
void bindPaneWidget(QPointer<WBaseLibrary> sidebarWidget, |
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.
QPointer only says: Be null if the references Object is delete. From Qt5 this is exactly the same as a weak reference by QWeakPointer. I think this should not be part of an interface, because it is pointless here.
In this case the LibrarySidebarExpandedManager will store the pointer. It should be guaranteed that the lifetime is controlled by someone else. In case of shared / weak pinter, we would pass a shared pointer and store it as weak pointer.
I think in this case we can use our parented_ptr<> meaning: Give me a QObject that has a parent. Than we can store it as QPointer
It has been added to LibraryPaneManager and LibrarySidebarExpandedManager and also to the library and the legacy skin parser calls.
TrackPointer m_pSelectedTrack; | ||
|
||
std::shared_ptr<TreeItemModel> m_childModel; |
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.
This protected m_childModel is a bit scary for me, because it is instantiated in the inherited classes.
Can we move it to the inherited classes and add here an abstract getChildModel instead?
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.
and when it remains a pointer type, it should be called m_pChildMode, .... but is it required to be a pointer.
delete m_childModel; | ||
m_childModel = m_pHistoryTreeModel = new HistoryTreeModel(this, m_pTrackCollection); | ||
m_childModel = m_pHistoryTreeModel = | ||
std::make_shared<HistoryTreeModel>(this, m_pTrackCollection); |
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.
Ah yes, m_pHistoryTreeModel and m_childModel could be merged to a non pointer member.
We just need to implement the abstract getChildModel here.
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.
Did you consider to get rid of this shared pointer.
We just tor it in the object and the inherited base object.
To finish this PR we must wait until mixxxdj#1161 is completed or there's something that I can do meanwhile? |
It's merged now, thanks for the patience |
I am just working on merging master to daschuer:jmigual-library-redesign |
Now that we've solved the coding style issues at the project level and forked off the 2.1 branch I think we can get this library redesign merged in the next week or so with some good collaboration, what do you guys think? |
We have the 2.1 branch now, mainly for testing th CI. I think most of the work currently done in master will be still merged to 2.1. But that should us not bother here. If we think we are ready we can advertise this for the next release. |
Yes I will be adding changing all the naked pointers during this week and try to fix as many bugs as possible. |
Great, Thank you! |
…edesign' Conflicts: src/library/features/crates/cratefeature.cpp
Ok, I've fixed it. |
By the way I don't know why but SQLITE3 crashes when creating a collation when using QT5.7.1.0 on Ubuntu 16.04 |
Let me take care of the move constructor issue, we don't want to disperse
Joan's time too much
…On 10 Feb. 2017 21:14, "Daniel Schürmann" ***@***.***> wrote:
Strange, gcc is still trying to use the type conversion function.
What happens if you comment it out?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#15 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACsA4gYuiN37yIDV6u5hspV3Rd2soiUqks5rbFSsgaJpZM4LsvU0>
.
|
It seems that the problem is when casting from a different type. |
These are the same lines that have been giving us problems before commenting the type conversion function. |
I can't even get mixxx to start compiling with gcc-4.8 on Ubuntu 16.10...
Scons (v 2.5) complains that "A compiler with C++11 support is required." I
guess they removed support for 4.8 :-/
gcc-4.9 is working so I'll see if I can reproduce with that.
…On Fri, Feb 10, 2017 at 9:20 PM, Joan ***@***.***> wrote:
These are the same lines that have been giving us problem before
commenting the type conversion function.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#15 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACsA4l-ReNFiUyJtPISQ-lcBvyc4f3w2ks5rbFYcgaJpZM4LsvU0>
.
|
There is still this redundant shared pointer member. Can't we get rid of it?
|
Yes, now it's done 😊 By the way I found that the issue with SQLITE3 and Qt5 is not due to the Ubuntu distributed version of Qt5 but the version distributed with the Qt Maintenance Tool, has anyone tried using it to install Qt5? In Windows it crashes too and I have to compile Qt5 to get it to work. |
Thank you. Did you forget to push? |
Oh I added the changes in the wrong branch sorry! I'll try to fix it |
Conflicts: src/library/features/mixxxlibrary/mixxxlibraryfeature.cpp
Done |
Thank you! Sorry for beeing not able to merge this earlier. |
This doesn't compile due to a typo :-/ src/library/features/mixxxlibrary/mixxxlibraryfeature.cpp:149:22: error: ‘pSidebaar’ was not declared in this scope
return std::move(pSidebaar); |
Do you not get the CI check on your fork? |
Oh sorry it's due to a bad merge. Now I've fixed it and checked that it compiles #16.
Yes but it takes about 30 minutes to compile and send me a failed email 😅 |
I got gcc4.8 up and running on my old laptop and was able to confirm that it doesn't like the polymorphic type. If we return |
Actually #include <iostream>
#include "util/parented_ptr.h"
#include "util/memory.h"
using namespace std;
struct Test : public QObject {
void foo() { std::cout << "foo" << std::endl; }
};
unique_ptr<QObject> foo()
{
auto p = make_unique<Test>();
return p; // 1
//return move( p ); // 2
} |
This means we will drop Ubuntu Precise support. This issue here is IMHO not important enough for the switch. Looking to the issue again, it is probably not bad to have the
The only issue is that it is a source of CI errors, because without it it fails only on some targets. |
I have a solution: template <typename U>
operator parented_ptr<U>() const {
return *this;
} Works, unfortunately it allows also up-casts. So we should make it gcc 4 only. Alternatively we can define operator parented_ptr<QWidget>() const {
return *this;
} this does not work. It compiles, but does not make a change, maybe this is a implicit rule anyway. operator parented_ptr<typename std::enable_if<std::is_convertible<U*, T*>::value>() const {
return *this;
} |
How about this solution: template <typename U>
operator parented_ptr<U>() const {
static_assert(std::is_convertible<T*, U*>::value,
"No implicit conversion from T* to U* found.");
return *this;
} |
I like this last solution. |
Precise is already dropped for 2.1 -- did you mean Trusty? There is already a new LTS release with Xenial. By the time 2.2 comes out it will already have been plenty of time for users to upgrade (it's already been nearly a year). I agree this is a pretty minor reason to force a switch. I'm more concerned that Trusty has an ancient version of Qt5 (5.2) so continuing support for it will cause an unnecessary burden on development. |
Yes, of cause Trusty. We will see, what is the next reason for a drop, the time will come. :-) |
Deere 2.1 layout & color fixes
controllers/bulk: Fix BulkController constructor
…h sync When loading a track that is not yet present in the library (and thus doesn't have any BPM because it hasn't been analyzed yet) while another deck is playing and both decks have sync enabled, a debug assertion is triggered: DEBUG ASSERT: "isValid()" in function double mixxx::Bpm::value() const at src/track/bpm.h:53 Aborted (core dumped) The backtrace looks as follows: #0 0x00007f175c87234c in __pthread_kill_implementation () at /usr/lib/libc.so.6 #1 0x00007f175c8254b8 in raise () at /usr/lib/libc.so.6 #2 0x00007f175c80f534 in abort () at /usr/lib/libc.so.6 #3 0x00007f175cf05ee4 in qt_assert(char const*, char const*, int) () at /usr/lib/libQt5Core.so.5 #4 0x000055deb2e67e1c in mixxx::(anonymous namespace)::handleMessage(QtMsgType, QMessageLogContext const&, QString const&) (type=<optimized out>, context=<optimized out>, input=<optimized out>) at src/util/logging.cpp:355 #5 0x00007f175cf47128 in () at /usr/lib/libQt5Core.so.5 #6 0x00007f175cf3fd8a in () at /usr/lib/libQt5Core.so.5 #7 0x00007f175cf06526 in QMessageLogger::critical(char const*, ...) const () at /usr/lib/libQt5Core.so.5 #8 0x000055deb2e5c720 in mixxx_debug_assert(char const*, char const*, int, char const*) (assertion=assertion@entry=0x55deb39bd0db "isValid()", file=file@entry=0x55deb39bbf30 "src/track/bpm.h", line=line@entry=53, function=function@entry=0x55deb39bbf08 "double mixxx::Bpm::value() const") at gsrc/util/assert.h:9 #9 0x000055deb2ee7e7e in mixxx_debug_assert_return_true(char const*, char const*, int, char const*) (function=0x55deb39bbf08 "double mixxx::Bpm::value() const", line=53, file=0x55deb39bbf30 "src/track/bpm.h", assertion=0x55deb39bd0db "isValid()") at gsrc/util/assert.h:18 #10 mixxx::Bpm::value() const (this=<synthetic pointer>) at src/track/bpm.h:53 #11 mixxx::operator*(mixxx::Bpm, double) (multiple=1, bpm=...) at src/track/bpm.h:160 #12 SyncControl::setLocalBpm(mixxx::Bpm) (this=<optimized out>, localBpm=...) at src/engine/sync/synccontrol.cpp:567 #13 0x000055deb34c7ba3 in EngineBuffer::postProcess(int) (this=0x55deb56eb060, iBufferSize=2048) at src/engine/enginebuffer.cpp:1318 #14 0x000055deb3139023 in EngineMaster::processChannels(int) (this=0x55deb5449440, iBufferSize=<optimized out>) at src/engine/enginemaster.cpp:383 #15 0x000055deb31394f7 in EngineMaster::process(int) (this=0x55deb5449440, iBufferSize=iBufferSize@entry=2048) at src/engine/enginemaster.cpp:410 #16 0x000055deb2f91d0b in SoundManager::onDeviceOutputCallback(long) (this=<optimized out>, iFramesPerBuffer=iFramesPerBuffer@entry=1024) at src/soundio/soundmanager.cpp:596 #17 0x000055deb32dd794 in SoundDevicePortAudio::callbackProcessClkRef(long, float*, float const*, PaStreamCallbackTimeInfo const*, unsigned long) (this=0x55deb553e6b0, framesPerBuffer=1024, out=<optimized out>, in=<optimized out>, timeInfo=<optimized out>, statusFlags=<optimized out>) at src/soundio/sounddeviceportaudio.cpp:965 This happens because `newLocalBpm` is invalid when `localBpm` is invalid. Trying to do sync decks while no tempo information is available does not make sense, so we only synchronize decks if the local BPM is available.
I've replaced some naked new pointers. Now I've used
QSharedPointer
instead. Also I've added some initializer lists now that we suport VS2015.