MarkSim
Topic Author
Posts: 30
Joined: 20 Apr 2021, 18:59

Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 10:51

I'm using an std::map to sort an ObservableCollection.

The type I'm containing is defined like this:
class MyType : public NoesisApp::NotifyPropertyChangedBase
My ObservableCollection is declared like this:
Noesis::Ptr<Noesis::ObservableCollection<MyType>> myCollection;
And I am populating it like this:
myCollection->Add(Noesis::MakePtr<MyType>(item));
I had trouble sorting the ObservableCollection directly; it seemed to cause the association ListBox to fall over (I was doing a crude bubble sort so items were being swapped a lot).

So I decided to use an std::map and std::vector (for duplicate keys) like this:
std::map<std::string, std::vector<MyType*>> sortedItems;

    // Populate the std::map using the sort key as the key, and storing the item as the value.

    for (int i = 0; i < itemCount; ++i) {
        auto key = GetSortKey(i, itemIndex);
        auto findIt = sortedItems.find(key);
        if (findIt != sortedItems.end()) {
            findIt->second.push_back(myCollection->Get(i));
        } else {
            sortedItems[key].push_back(myCollection->Get(i));
        }
    }

    auto currentSelectedItem = GetSelectedItem();

    myCollection->Clear();

    if (sortDescending) {
        for (auto it = sortedItems.rbegin(); it != sortedItems.rend(); ++it) {
            for (auto item : it->second) {
                myCollection->Add(item);
            }
        }
    } else {
        for (auto it = sortedItems.begin(); it != sortedItems.end(); ++it) {
            for (auto item : it->second) {
                myCollection->Add(item);
            }
        }
    }
It seems to crash when I do this:
myCollection->Add(item);
Here:
void* Noesis::Cast(const TypeClass* destType, BaseObject* source)
{
    NS_ASSERT(destType != 0);

    if (source != 0)
    {
        const TypeClass* typeClass = source->GetClassType();  <====== READ ACCESS VIOLATION
I *was* populating it like this:
myCollection->Add(new MyType(item));
And that worked fine, but this caused a memory leak, and it seemed proper to use MakePtr. Must admit, I haven't quite got my head around Noesis's ref counted pointers, they seem very different to std smart pointers!

What is the proper way of doing this?

Thanks.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 10:55

Must admit, I haven't quite got my head around Noesis's ref counted pointers, they seem very different to std smart pointers!
I assume you read our C++ Architecture Guide ?
 
MarkSim
Topic Author
Posts: 30
Joined: 20 Apr 2021, 18:59

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 11:01

I did, but may have missed something.

This stood out to me:
Ptr<> implicitly converts to raw pointers, so most of the times its usage is totally transparent and you don't need to care about the details.

So was hoping it would just work!

I will go read it again in case I missed something. I do need to fix it in a hurry so if there is an obvious quick fix, please let me know. I agree though I should really get my head around it. So far they've just worked fine.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 11:01

So I decided to use an std::map and std::vector (for duplicate keys) like this:
The problem with that code is that the only *hard* references to your items are in myCollection. When you clear that collection all the items are released (because probably they only have one reference). So your previously stored pointers in sortedItems are now garbage. You need to add an extra reference before the Clear (and later the corresponding release).
 
MarkSim
Topic Author
Posts: 30
Joined: 20 Apr 2021, 18:59

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 11:13

Ah yes, that makes sense, thank you - that is now fixed.

I don't yet totally get it; in the ObservableCollection it is templated to store MyType, not Ptr<MyType> - and when adding it accepts MyType* as the argument, so not sure why the Ptr<> part doesn't get lost in ObservableCollection which *looks like* it is storing just a MyType*, but it does get lost when storing a MyType* in an std container.

I know the item I am storing inherits from BaseRefCounted ...

I will spend some time with it once the deadline has passed so I can fully understand it.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 11:19

ObservableCollection inherits from BaseCollection who contains a:
Vector<Ptr<BaseComponent>> mItems;
But yes, the API of ObservableCollection could be improved to be more C++ friendly and we have future plans to improve all this and our reflection architecture to allow more native ways to provide collections using your own types (or std::map, std::vector for example).

Thanks for your feedback!
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Crash using std::map to sort items in ObservableCollection

17 Sep 2021, 19:33

Regarding your sort approach (using an intermediate map) I want to mention that you can use the Move method in ObservableCollection to sort your items without removing and adding them. This will perform a lot better as Move notifications just change the associated containers index (if collection is bound to an ItemsControl), instead of removing the container and adding a new one.
 
MarkSim
Topic Author
Posts: 30
Joined: 20 Apr 2021, 18:59

Re: Crash using std::map to sort items in ObservableCollection

21 Sep 2021, 13:47

Thanks - I did try that initialiy, admittedly using a crude bubble sort I knocked up. Worked fine in WPF, but it would seem to crash the view container when I ported it across. I could perhaps try it again, and if it still crashes, I will report it here.
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: Crash using std::map to sort items in ObservableCollection

21 Sep 2021, 13:54

Thanks for that, if you can reproduce the crash again and send us a dump we will fix it.

Who is online

Users browsing this forum: Google [Bot] and 74 guests