Skip to content
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

Fatal error: Can't compare indices belonging to different collections #2

Open
mikon63 opened this issue Aug 26, 2021 · 9 comments
Open

Comments

@mikon63
Copy link

mikon63 commented Aug 26, 2021

I am getting a strange runtime error after changing the aisShips Dictionary to the ThreadSafeDictionary:

Can't compare indices belonging to different collections

Following function is called by timer every 120 seconds. Every 20...30 minutes the app will crash with the above error. Error is caused by for (mmsi, aisShip) in aisShips
Given the time interval between crashes I suspect that the aisShips.removeValue(...) statement causes the trouble by removing a dictionary element from the dictionary. This was not an issue with the standard Dictionary.

`@objc func onAisPrune(_ timer: Timer)
{
let currentdate = Date()

    for (mmsi, aisShip) in aisShips
    {
        if currentdate.timeIntervalSince(aisShip.aisdate) > 20 * 60
        {
            nmea.dbLock.wait()
            aisShips.removeValue(forKey: mmsi)
            aisTracks.removeValue(forKey: mmsi)
            nmea.dbLock.signal()
            
            DispatchQueue.main.async {
                MapFactory.shared.removeAisTarget(mmsi: mmsi)
            }
            
        }
    }
}`
@mikon63
Copy link
Author

mikon63 commented Aug 26, 2021

Same happens for aisShips.forEach { (mmsi: String, aisShip: Aisdata) ... }

@chrisvoronin
Copy link

yep we have a very similar implementation for our thread safe dictionary, same error. Was looking to see if anyone ran into that and solved it.

@macaaw
Copy link

macaaw commented Jan 11, 2023

I'm also getting this. Has there been any fixes for this?

@iThink32
Copy link
Owner

@mikon63 @macaaw apologies for the long delay in replying, are you sure removeValue is the culprit? if so then ill try to make time to add a thread safe implementation for that as well.

@mikon63
Copy link
Author

mikon63 commented Jan 13, 2023

I believe the error results from traversing the dictionary and within this loop removing items, though I can't be absolutely sure. I found a workaround by writing the elements I need to remove in an array first and then traversing the new array to remove elements in the dictionary, so I am actually working with two independent collections now.

@objc func onAisPrune(_ timer: Timer)
{
let currentdate = Date()
var mmsiToRemove : [String] = []

    mmsiToRemove = aisShips.filter({ (mmsi: String, aisShip: Aisdata) in
        return currentdate.timeIntervalSince(aisShip.aisdate) > 20 * 60
    }).map({ (mmsi: String, aisShip: Aisdata) -> String in
        return mmsi
    })

    for mmsi in mmsiToRemove
    {
        nmea.dbLock.wait()
        aisShips.removeValue(forKey: mmsi)
        aisTracks.removeValue(forKey: mmsi)
        nmea.dbLock.signal()
        
        DispatchQueue.main.async {
            MapFactory.shared.removeAisTarget(mmsi: mmsi)
        }
    }
}

@iThink32
Copy link
Owner

Unfortunately guys I've tried creating an iterator and making that thread safe but that too doesn't work. As suggested the issue is in modifying a dictionary while iterating the same. Thinking about fixes will update you on the same.

@iThink32
Copy link
Owner

For all those who are on iOS 13+ do check out actors, it will help in removing the dependency on our good old DispatchQueue.

@brandFromNSK
Copy link

I got this too. Try solution by adding code:

    public func forEach(_ body: ((key: V, value: T)) throws -> Void) rethrows {
        try concurrentQueue.sync {
            try dictionary.forEach(body)
        }
    }

@nikbhatt-cu
Copy link

The removeValue and removeAll funds do an async dispatch, rather than sync. Could that be an issue? It's easy to switch to code to sync and try reproducing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants