mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
bugfix: fixed a race condition potentially causing last write wins
This commit is contained in:
parent
723eaa0076
commit
d4b6f611f8
1 changed files with 16 additions and 11 deletions
|
|
@ -31,36 +31,38 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
|
|
||||||
public ModCollection Create(string name, int index, ModCollection? duplicate)
|
public ModCollection Create(string name, int index, ModCollection? duplicate)
|
||||||
{
|
{
|
||||||
var newCollection = duplicate?.Duplicate(name, CurrentCollectionId, index)
|
var localId = AllocateNextId();
|
||||||
?? ModCollection.CreateEmpty(name, CurrentCollectionId, index, _modStorage.Count);
|
var newCollection = duplicate?.Duplicate(name, localId, index)
|
||||||
Add(newCollection);
|
?? ModCollection.CreateEmpty(name, localId, index, _modStorage.Count);
|
||||||
|
AddAtLocalId(newCollection, localId);
|
||||||
return newCollection;
|
return newCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModCollection CreateFromData(Guid id, string name, int version, Dictionary<string, ModSettings.SavedSettings> allSettings,
|
public ModCollection CreateFromData(Guid id, string name, int version, Dictionary<string, ModSettings.SavedSettings> allSettings,
|
||||||
IReadOnlyList<string> inheritances)
|
IReadOnlyList<string> inheritances)
|
||||||
{
|
{
|
||||||
|
var localId = AllocateNextId();
|
||||||
var newCollection = ModCollection.CreateFromData(_saveService, _modStorage,
|
var newCollection = ModCollection.CreateFromData(_saveService, _modStorage,
|
||||||
new ModCollectionIdentity(id, CurrentCollectionId, name, Count), version, allSettings, inheritances);
|
new ModCollectionIdentity(id, localId, name, Count), version, allSettings, inheritances);
|
||||||
Add(newCollection);
|
AddAtLocalId(newCollection, localId);
|
||||||
return newCollection;
|
return newCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModCollection CreateTemporary(string name, int index, int globalChangeCounter)
|
public ModCollection CreateTemporary(string name, int index, int globalChangeCounter)
|
||||||
{
|
{
|
||||||
var newCollection = ModCollection.CreateTemporary(name, CurrentCollectionId, index, globalChangeCounter);
|
var localId = AllocateNextId();
|
||||||
Add(newCollection);
|
var newCollection = ModCollection.CreateTemporary(name, localId, index, globalChangeCounter);
|
||||||
|
AddAtLocalId(newCollection, localId);
|
||||||
return newCollection;
|
return newCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks> Atomically add to _collectionLocal and increments _currentCollectionIdValue. </remarks>
|
/// <remarks> Atomically add to _collectionLocal at the id given. </remarks>
|
||||||
private void Add(ModCollection newCollection)
|
private void AddAtLocalId(ModCollection newCollection, LocalCollectionId id)
|
||||||
{
|
{
|
||||||
_collectionsByLocal.AddOrUpdate(CurrentCollectionId,
|
_collectionsByLocal.AddOrUpdate(id,
|
||||||
static (_, newColl) => newColl,
|
static (_, newColl) => newColl,
|
||||||
static (_, _, newColl) => newColl,
|
static (_, _, newColl) => newColl,
|
||||||
newCollection);
|
newCollection);
|
||||||
Interlocked.Increment(ref _currentCollectionIdValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(ModCollection collection)
|
public void Delete(ModCollection collection)
|
||||||
|
|
@ -87,6 +89,9 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
/// <remarks> Starts at 1 because the empty collection gets Zero. </remarks>
|
/// <remarks> Starts at 1 because the empty collection gets Zero. </remarks>
|
||||||
public LocalCollectionId CurrentCollectionId => new(_currentCollectionIdValue);
|
public LocalCollectionId CurrentCollectionId => new(_currentCollectionIdValue);
|
||||||
|
|
||||||
|
private LocalCollectionId AllocateNextId ()
|
||||||
|
=> new(Interlocked.Increment(ref _currentCollectionIdValue));
|
||||||
|
|
||||||
/// <summary> Default enumeration skips the empty collection. </summary>
|
/// <summary> Default enumeration skips the empty collection. </summary>
|
||||||
public IEnumerator<ModCollection> GetEnumerator()
|
public IEnumerator<ModCollection> GetEnumerator()
|
||||||
=> _collections.Skip(1).GetEnumerator();
|
=> _collections.Skip(1).GetEnumerator();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue