@@ -311,8 +311,16 @@ module ModDBInterop =
311311 List.item delIdx moddb.DeletionMods
312312 | n -> failwithf " invalid mod index: %A " i
313313
314- // technically, because I use an exclusive lock below, this doesn't need to be a concurrent dictionary
315- let modLoadThread = new System.Collections.Concurrent.ConcurrentDictionary< string, System.Threading.Thread>()
314+ /// Used to track the loading thread for a mod (see lodModData for more details).
315+ type LoadInfo = {
316+ Thread: System .Threading .Thread
317+ /// When the database is reloaded this will change, allowing a new set of loads. This is useful
318+ /// if some of the mods had errors that have been corrected.
319+ MeshRelationId: int
320+ LastLoadHadError: option < bool >
321+ }
322+
323+ let modLoadThread = new System.Collections.Concurrent.ConcurrentDictionary< string, LoadInfo>()
316324
317325 /// Load the mod data for mod i. This is assumed to be an index into the mesh relation list.
318326 /// If the mesh relation is already built, this does nothing (the mod is not reloaded).
@@ -329,30 +337,56 @@ module ModDBInterop =
329337 /// to this function. The native code should observe that the (new) mesh relation's data is still
330338 /// unavailable and trigger a another call to this function on an ongoing basis until the old thread
331339 /// finishes and a new one can be started.
332- let loadModData ( i ) =
340+ let loadModData ( i ) =
333341 let mutable loadState = 0 // not available
334- try
342+ try
335343 let moddb = State.Data.Moddb
336- if i < moddb.MeshRelations.Length then
344+ if i < moddb.MeshRelations.Length then
337345 let meshrel = List.item i ( moddb.MeshRelations)
338-
339- if meshrel.IsBuilt then
346+
347+ if meshrel.IsBuilt then
340348 loadState <- 1 // loaded
341- else
349+ else
342350 let loadKey = i.ToString() + meshrel.DBMod.Name + meshrel.DBRef.Name
351+ let currentMeshRelId = meshrel.GetHashCode()
343352
344- Locking.write( fun _ ->
345- let ok , mlt = modLoadThread.TryGetValue loadKey
346- if not ok || ( ok && not mlt.IsAlive) then
347- let loadit () =
353+ let loadit () =
354+ let ok , currInfo = modLoadThread.TryGetValue loadKey
355+ if ok then
356+ try
357+ //log.Info "beginning new load for key %A with meshrel id %A (curr load info: %A)" loadKey currentMeshRelId currInfo
348358 meshrel.Build() |> ignore
349- let t = new System.Threading.Thread( new System.Threading.ThreadStart( loadit) )
350- t.Start()
351- modLoadThread.AddOrUpdate( loadKey, t, ( fun _ ( oldT ) -> t)) |> ignore
352- loadState <- 2 // load was started
353- else
354- loadState <- 3 // a started load is still pending
355- )
359+ let newInfo = { currInfo with LastLoadHadError = Some( false ) }
360+ modLoadThread.TryUpdate( loadKey, newInfo, currInfo) |> ignore
361+ with
362+ | e ->
363+ // this is in a separate thread so log explicitly to make sure it goes to output log
364+ log.Error " Mesh relation build exception: %A " e
365+ let newInfo = { currInfo with LastLoadHadError = Some( true ) }
366+ modLoadThread.TryUpdate( loadKey, newInfo, currInfo) |> ignore
367+ else
368+ log.Error " load info for mod %A not found" meshrel.DBMod.Name
369+
370+ let startNewLoad () =
371+ let t = new System.Threading.Thread( new System.Threading.ThreadStart( loadit))
372+ let newLoadInfo = { Thread = t; MeshRelationId = currentMeshRelId; LastLoadHadError = None }
373+ modLoadThread.AddOrUpdate( loadKey, newLoadInfo, ( fun _ _ -> newLoadInfo)) |> ignore
374+ t.Start()
375+ loadState <- 2 // load was started
376+
377+ Locking.write ( fun _ ->
378+ match modLoadThread.TryGetValue( loadKey) with
379+ | ( true , loadInfo) ->
380+ //log.Info "Found existing load entry: %A (curr meshrel is: %A)" loadInfo currentMeshRelId
381+ if loadInfo.MeshRelationId = currentMeshRelId && loadInfo.LastLoadHadError = Some true then
382+ loadState <- 4 // error encountered previously, do not start a new load
383+ elif loadInfo.Thread.IsAlive then
384+ loadState <- 3 // a started load is still pending
385+ else
386+ startNewLoad()
387+ | ( false , _) ->
388+ startNewLoad()
389+ )
356390 loadState
357391 with
358392 | e ->
0 commit comments