mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Ensure consistency by using ConcurrentList (fixes #36)
This commit is contained in:
@@ -93,7 +93,7 @@ have a current entry in the DAT index.";
|
||||
|
||||
foreach (string key in df.Items.Keys)
|
||||
{
|
||||
List<DatItem> datItems = df.Items[key];
|
||||
ConcurrentList<DatItem> datItems = df.Items[key];
|
||||
foreach (Rom rom in datItems)
|
||||
{
|
||||
// If we care about if the file exists, check the databse first
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace RombaSharp.Features
|
||||
IEnumerable<string> keys = depot.Items.Keys;
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<DatItem> roms = depot.Items[key];
|
||||
ConcurrentList<DatItem> roms = depot.Items[key];
|
||||
foreach (Rom rom in roms)
|
||||
{
|
||||
if (hashes.Contains(rom.SHA1))
|
||||
|
||||
160
SabreTools.Core/ConcurrentList.cs
Normal file
160
SabreTools.Core/ConcurrentList.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Thread-safe list class
|
||||
/// </summary>
|
||||
public class ConcurrentList<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList
|
||||
{
|
||||
private List<T> _list = new List<T>();
|
||||
private object _lock = new object();
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get { lock (_lock) return _list[index]; }
|
||||
set { lock (_lock) _list[index] = value; }
|
||||
}
|
||||
|
||||
object IList.this[int index]
|
||||
{
|
||||
get { lock (_lock) return ((IList)_list)[index]; }
|
||||
set { lock (_lock) ((IList)_list)[index] = value; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { lock (_lock) return _list.Count; }
|
||||
}
|
||||
|
||||
public bool IsFixedSize => ((IList)_list).IsFixedSize;
|
||||
|
||||
public bool IsReadOnly => ((IList)_list).IsReadOnly;
|
||||
|
||||
public bool IsSynchronized => ((ICollection)_list).IsSynchronized;
|
||||
|
||||
public object SyncRoot => ((ICollection)_list).SyncRoot;
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.Add(item);
|
||||
}
|
||||
|
||||
public int Add(object value)
|
||||
{
|
||||
lock (_lock)
|
||||
return ((IList)_list).Add(value);
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> values)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.AddRange(values);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
_list.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (_lock)
|
||||
return _list.Contains(item);
|
||||
}
|
||||
|
||||
public bool Contains(object value)
|
||||
{
|
||||
lock (_lock)
|
||||
return ((IList)_list).Contains(value);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
lock (_lock)
|
||||
((ICollection)_list).CopyTo(array, index);
|
||||
}
|
||||
|
||||
public void ForEach(Action<T> action)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.ForEach(action);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
lock (_lock)
|
||||
return _list.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
lock (_lock)
|
||||
return ((IEnumerable)_list).GetEnumerator();
|
||||
}
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
lock (_lock)
|
||||
return _list.IndexOf(item);
|
||||
}
|
||||
|
||||
public int IndexOf(object value)
|
||||
{
|
||||
lock (_lock)
|
||||
return ((IList)_list).IndexOf(value);
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.Insert(index, item);
|
||||
}
|
||||
|
||||
public void Insert(int index, object value)
|
||||
{
|
||||
lock (_lock)
|
||||
((IList)_list).Insert(index, value);
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
lock (_lock)
|
||||
return _list.Remove(item);
|
||||
}
|
||||
|
||||
public void Remove(object value)
|
||||
{
|
||||
lock (_lock)
|
||||
((IList)_list).Remove(value);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.RemoveAt(index);
|
||||
}
|
||||
|
||||
public void SetInternalList(List<T> list)
|
||||
{
|
||||
lock (_lock)
|
||||
_list = list;
|
||||
}
|
||||
|
||||
public void Sort(Comparison<T> comparison)
|
||||
{
|
||||
lock (_lock)
|
||||
_list.Sort(comparison);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
SabreTools.Core/ConcurrentListExtensions.cs
Normal file
15
SabreTools.Core/ConcurrentListExtensions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SabreTools.Core
|
||||
{
|
||||
public static class ConcurrentListExtensions
|
||||
{
|
||||
public static ConcurrentList<T> ToConcurrentList<T>(this IEnumerable<T> values)
|
||||
{
|
||||
var list = new ConcurrentList<T>();
|
||||
list.SetInternalList(values.ToList());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,7 +513,7 @@ namespace SabreTools.DatFiles
|
||||
/// <param name="datItems">DatItems to check</param>
|
||||
/// <returns>True if the machine contains at least one writable item, false otherwise</returns>
|
||||
/// <remarks>Empty machines are kept with this</remarks>
|
||||
protected bool ContainsWritable(List<DatItem> datItems)
|
||||
protected bool ContainsWritable(ConcurrentList<DatItem> datItems)
|
||||
{
|
||||
// Empty machines are considered writable
|
||||
if (datItems == null || datItems.Count == 0)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@@ -141,7 +140,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@@ -463,7 +462,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@@ -135,7 +134,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@@ -130,7 +129,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items[key];
|
||||
ConcurrentList<DatItem> datItems = Items[key];
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -282,7 +281,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1372,7 +1372,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -804,7 +804,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using SabreTools.Core;
|
||||
using SabreTools.DatItems;
|
||||
|
||||
namespace SabreTools.DatFiles.Formats
|
||||
@@ -51,7 +51,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -693,7 +693,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -566,7 +566,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -391,7 +391,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -364,7 +364,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
using SabreTools.Core;
|
||||
using SabreTools.DatItems;
|
||||
|
||||
namespace SabreTools.DatFiles.Formats
|
||||
@@ -208,7 +208,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@@ -124,7 +123,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -613,7 +613,7 @@ namespace SabreTools.DatFiles.Formats
|
||||
// Use a sorted list of games to output
|
||||
foreach (string key in Items.SortedKeys)
|
||||
{
|
||||
List<DatItem> datItems = Items.FilteredItems(key);
|
||||
ConcurrentList<DatItem> datItems = Items.FilteredItems(key);
|
||||
|
||||
// If this machine doesn't contain any writable items, skip
|
||||
if (!ContainsWritable(datItems))
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace SabreTools.DatFiles
|
||||
/// Item dictionary with statistics, bucketing, and sorting
|
||||
/// </summary>
|
||||
[JsonObject("items"), XmlRoot("items")]
|
||||
public class ItemDictionary : IDictionary<string, List<DatItem>>
|
||||
public class ItemDictionary : IDictionary<string, ConcurrentList<DatItem>>
|
||||
{
|
||||
#region Private instance variables
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace SabreTools.DatFiles
|
||||
/// <summary>
|
||||
/// Internal dictionary for the class
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, List<DatItem>> items;
|
||||
private readonly ConcurrentDictionary<string, ConcurrentList<DatItem>> items;
|
||||
|
||||
/// <summary>
|
||||
/// Lock for statistics calculation
|
||||
@@ -363,7 +363,7 @@ namespace SabreTools.DatFiles
|
||||
/// Passthrough to access the file dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">Key in the dictionary to reference</param>
|
||||
public List<DatItem> this[string key]
|
||||
public ConcurrentList<DatItem> this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -417,7 +417,7 @@ namespace SabreTools.DatFiles
|
||||
/// </summary>
|
||||
/// <param name="key">Key in the dictionary to add to</param>
|
||||
/// <param name="value">Value to add to the dictionary</param>
|
||||
public void Add(string key, List<DatItem> value)
|
||||
public void Add(string key, ConcurrentList<DatItem> value)
|
||||
{
|
||||
AddRange(key, value);
|
||||
}
|
||||
@@ -569,7 +569,7 @@ namespace SabreTools.DatFiles
|
||||
/// </summary>
|
||||
/// <param name="key">Key in the dictionary to add to</param>
|
||||
/// <param name="value">Value to add to the dictionary</param>
|
||||
public void AddRange(string key, List<DatItem> value)
|
||||
public void AddRange(string key, ConcurrentList<DatItem> value)
|
||||
{
|
||||
// Explicit lock for some weird corner cases
|
||||
lock (key)
|
||||
@@ -678,30 +678,27 @@ namespace SabreTools.DatFiles
|
||||
{
|
||||
// If the key is missing from the dictionary, add it
|
||||
if (!items.ContainsKey(key))
|
||||
items.TryAdd(key, new List<DatItem>());
|
||||
items.TryAdd(key, new ConcurrentList<DatItem>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of filtered items for a given key
|
||||
/// </summary>
|
||||
/// <param name="key">Key in the dictionary to retrieve</param>
|
||||
public List<DatItem> FilteredItems(string key)
|
||||
public ConcurrentList<DatItem> FilteredItems(string key)
|
||||
{
|
||||
lock (key)
|
||||
{
|
||||
// Get the list, if possible
|
||||
List<DatItem> fi = items[key];
|
||||
ConcurrentList<DatItem> fi = items[key];
|
||||
if (fi == null)
|
||||
return new List<DatItem>();
|
||||
return new ConcurrentList<DatItem>();
|
||||
|
||||
// Filter the list
|
||||
fi = fi.Where(i => i != null)
|
||||
return fi.Where(i => i != null)
|
||||
.Where(i => !i.Remove)
|
||||
.Where(i => i.Machine?.Name != null)
|
||||
.ToList();
|
||||
|
||||
// Return the list
|
||||
return fi;
|
||||
.ToConcurrentList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,7 +764,7 @@ namespace SabreTools.DatFiles
|
||||
}
|
||||
|
||||
// Remove the key from the dictionary
|
||||
items[key] = new List<DatItem>();
|
||||
items[key] = new ConcurrentList<DatItem>();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -935,7 +932,7 @@ namespace SabreTools.DatFiles
|
||||
{
|
||||
bucketedBy = ItemKey.NULL;
|
||||
mergedBy = DedupeType.None;
|
||||
items = new ConcurrentDictionary<string, List<DatItem>>();
|
||||
items = new ConcurrentDictionary<string, ConcurrentList<DatItem>>();
|
||||
logger = new Logger(this);
|
||||
}
|
||||
|
||||
@@ -1010,7 +1007,7 @@ namespace SabreTools.DatFiles
|
||||
Parallel.ForEach(keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
// Get the possibly unsorted list
|
||||
List<DatItem> sortedlist = this[key].ToList();
|
||||
ConcurrentList<DatItem> sortedlist = this[key].ToConcurrentList();
|
||||
|
||||
// Sort the list of items to be consistent
|
||||
DatItem.Sort(ref sortedlist, false);
|
||||
@@ -1031,7 +1028,7 @@ namespace SabreTools.DatFiles
|
||||
Parallel.ForEach(keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
// Get the possibly unsorted list
|
||||
List<DatItem> sortedlist = this[key];
|
||||
ConcurrentList<DatItem> sortedlist = this[key];
|
||||
|
||||
// Sort the list of items to be consistent
|
||||
DatItem.Sort(ref sortedlist, false);
|
||||
@@ -1069,8 +1066,8 @@ namespace SabreTools.DatFiles
|
||||
var keys = items.Keys.ToList();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<DatItem> oldItemList = items[key];
|
||||
List<DatItem> newItemList = oldItemList.Where(i => !i.Remove).ToList();
|
||||
ConcurrentList<DatItem> oldItemList = items[key];
|
||||
ConcurrentList<DatItem> newItemList = oldItemList.Where(i => !i.Remove).ToConcurrentList();
|
||||
|
||||
Remove(key);
|
||||
AddRange(key, newItemList);
|
||||
@@ -1083,9 +1080,9 @@ namespace SabreTools.DatFiles
|
||||
/// <param name="datItem">Item to try to match</param>
|
||||
/// <param name="sorted">True if the DAT is already sorted accordingly, false otherwise (default)</param>
|
||||
/// <returns>List of matched DatItem objects</returns>
|
||||
public List<DatItem> GetDuplicates(DatItem datItem, bool sorted = false)
|
||||
public ConcurrentList<DatItem> GetDuplicates(DatItem datItem, bool sorted = false)
|
||||
{
|
||||
List<DatItem> output = new List<DatItem>();
|
||||
ConcurrentList<DatItem> output = new ConcurrentList<DatItem>();
|
||||
|
||||
// Check for an empty rom list first
|
||||
if (TotalCount == 0)
|
||||
@@ -1099,8 +1096,8 @@ namespace SabreTools.DatFiles
|
||||
return output;
|
||||
|
||||
// Try to find duplicates
|
||||
List<DatItem> roms = this[key];
|
||||
List<DatItem> left = new List<DatItem>();
|
||||
ConcurrentList<DatItem> roms = this[key];
|
||||
ConcurrentList<DatItem> left = new ConcurrentList<DatItem>();
|
||||
for (int i = 0; i < roms.Count; i++)
|
||||
{
|
||||
DatItem other = roms[i];
|
||||
@@ -1146,7 +1143,7 @@ namespace SabreTools.DatFiles
|
||||
return false;
|
||||
|
||||
// Try to find duplicates
|
||||
List<DatItem> roms = this[key];
|
||||
ConcurrentList<DatItem> roms = this[key];
|
||||
return roms.Any(r => datItem.Equals(r));
|
||||
}
|
||||
|
||||
@@ -1165,7 +1162,7 @@ namespace SabreTools.DatFiles
|
||||
// Loop through and add
|
||||
foreach (string key in items.Keys)
|
||||
{
|
||||
List<DatItem> datItems = items[key];
|
||||
ConcurrentList<DatItem> datItems = items[key];
|
||||
foreach (DatItem item in datItems)
|
||||
{
|
||||
AddItemStatistics(item);
|
||||
@@ -1258,45 +1255,45 @@ namespace SabreTools.DatFiles
|
||||
|
||||
#region IDictionary Implementations
|
||||
|
||||
public ICollection<List<DatItem>> Values => ((IDictionary<string, List<DatItem>>)items).Values;
|
||||
public ICollection<ConcurrentList<DatItem>> Values => ((IDictionary<string, ConcurrentList<DatItem>>)items).Values;
|
||||
|
||||
public int Count => ((ICollection<KeyValuePair<string, List<DatItem>>>)items).Count;
|
||||
public int Count => ((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).Count;
|
||||
|
||||
public bool IsReadOnly => ((ICollection<KeyValuePair<string, List<DatItem>>>)items).IsReadOnly;
|
||||
public bool IsReadOnly => ((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).IsReadOnly;
|
||||
|
||||
public bool TryGetValue(string key, out List<DatItem> value)
|
||||
public bool TryGetValue(string key, out ConcurrentList<DatItem> value)
|
||||
{
|
||||
return ((IDictionary<string, List<DatItem>>)items).TryGetValue(key, out value);
|
||||
return ((IDictionary<string, ConcurrentList<DatItem>>)items).TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, List<DatItem>> item)
|
||||
public void Add(KeyValuePair<string, ConcurrentList<DatItem>> item)
|
||||
{
|
||||
((ICollection<KeyValuePair<string, List<DatItem>>>)items).Add(item);
|
||||
((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
((ICollection<KeyValuePair<string, List<DatItem>>>)items).Clear();
|
||||
((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, List<DatItem>> item)
|
||||
public bool Contains(KeyValuePair<string, ConcurrentList<DatItem>> item)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<string, List<DatItem>>>)items).Contains(item);
|
||||
return ((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, List<DatItem>>[] array, int arrayIndex)
|
||||
public void CopyTo(KeyValuePair<string, ConcurrentList<DatItem>>[] array, int arrayIndex)
|
||||
{
|
||||
((ICollection<KeyValuePair<string, List<DatItem>>>)items).CopyTo(array, arrayIndex);
|
||||
((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, List<DatItem>> item)
|
||||
public bool Remove(KeyValuePair<string, ConcurrentList<DatItem>> item)
|
||||
{
|
||||
return ((ICollection<KeyValuePair<string, List<DatItem>>>)items).Remove(item);
|
||||
return ((ICollection<KeyValuePair<string, ConcurrentList<DatItem>>>)items).Remove(item);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, List<DatItem>>> GetEnumerator()
|
||||
public IEnumerator<KeyValuePair<string, ConcurrentList<DatItem>>> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<KeyValuePair<string, List<DatItem>>>)items).GetEnumerator();
|
||||
return ((IEnumerable<KeyValuePair<string, ConcurrentList<DatItem>>>)items).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
||||
@@ -526,14 +526,14 @@ namespace SabreTools.DatItems
|
||||
/// </summary>
|
||||
/// <param name="infiles">List of File objects representing the roms to be merged</param>
|
||||
/// <returns>A List of DatItem objects representing the merged roms</returns>
|
||||
public static List<DatItem> Merge(List<DatItem> infiles)
|
||||
public static ConcurrentList<DatItem> Merge(ConcurrentList<DatItem> infiles)
|
||||
{
|
||||
// Check for null or blank roms first
|
||||
if (infiles == null || infiles.Count == 0)
|
||||
return new List<DatItem>();
|
||||
return new ConcurrentList<DatItem>();
|
||||
|
||||
// Create output list
|
||||
List<DatItem> outfiles = new List<DatItem>();
|
||||
ConcurrentList<DatItem> outfiles = new ConcurrentList<DatItem>();
|
||||
|
||||
// Then deduplicate them by checking to see if data matches previous saved roms
|
||||
int nodumpCount = 0;
|
||||
@@ -637,10 +637,10 @@ namespace SabreTools.DatItems
|
||||
/// </summary>
|
||||
/// <param name="infiles">List of File objects representing the roms to be merged</param>
|
||||
/// <returns>A List of DatItem objects representing the renamed roms</returns>
|
||||
public static List<DatItem> ResolveNames(List<DatItem> infiles)
|
||||
public static ConcurrentList<DatItem> ResolveNames(ConcurrentList<DatItem> infiles)
|
||||
{
|
||||
// Create the output list
|
||||
List<DatItem> output = new List<DatItem>();
|
||||
ConcurrentList<DatItem> output = new ConcurrentList<DatItem>();
|
||||
|
||||
// First we want to make sure the list is in alphabetical order
|
||||
Sort(ref infiles, true);
|
||||
@@ -742,7 +742,7 @@ namespace SabreTools.DatItems
|
||||
/// <param name="roms">List of File objects representing the roms to be sorted</param>
|
||||
/// <param name="norename">True if files are not renamed, false otherwise</param>
|
||||
/// <returns>True if it sorted correctly, false otherwise</returns>
|
||||
public static bool Sort(ref List<DatItem> roms, bool norename)
|
||||
public static bool Sort(ref ConcurrentList<DatItem> roms, bool norename)
|
||||
{
|
||||
roms.Sort(delegate (DatItem x, DatItem y)
|
||||
{
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace SabreTools.DatTools
|
||||
List<string> keys = datFile.Items.Keys.ToList();
|
||||
Parallel.ForEach(keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key].ToList();
|
||||
List<DatItem> newItems = new List<DatItem>();
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> newItems = new ConcurrentList<DatItem>();
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
DatItem newItem = item;
|
||||
@@ -87,11 +87,11 @@ namespace SabreTools.DatTools
|
||||
// Then we do a hashwise comparison against the base DAT
|
||||
Parallel.ForEach(intDat.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> datItems = intDat.Items[key];
|
||||
List<DatItem> newDatItems = new List<DatItem>();
|
||||
ConcurrentList<DatItem> datItems = intDat.Items[key];
|
||||
ConcurrentList<DatItem> newDatItems = new ConcurrentList<DatItem>();
|
||||
foreach (DatItem datItem in datItems)
|
||||
{
|
||||
List<DatItem> dupes = datFile.Items.GetDuplicates(datItem, sorted: true);
|
||||
ConcurrentList<DatItem> dupes = datFile.Items.GetDuplicates(datItem, sorted: true);
|
||||
DatItem newDatItem = datItem.Clone() as DatItem;
|
||||
|
||||
// Replace fields from the first duplicate, if we have one
|
||||
@@ -117,8 +117,8 @@ namespace SabreTools.DatTools
|
||||
// Then we do a namewise comparison against the base DAT
|
||||
Parallel.ForEach(intDat.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> datItems = intDat.Items[key];
|
||||
List<DatItem> newDatItems = new List<DatItem>();
|
||||
ConcurrentList<DatItem> datItems = intDat.Items[key];
|
||||
ConcurrentList<DatItem> newDatItems = new ConcurrentList<DatItem>();
|
||||
foreach (DatItem datItem in datItems)
|
||||
{
|
||||
DatItem newDatItem = datItem.Clone() as DatItem;
|
||||
@@ -194,8 +194,8 @@ namespace SabreTools.DatTools
|
||||
// Standard Against uses hashes
|
||||
else
|
||||
{
|
||||
List<DatItem> datItems = intDat.Items[key];
|
||||
List<DatItem> keepDatItems = new List<DatItem>();
|
||||
ConcurrentList<DatItem> datItems = intDat.Items[key];
|
||||
ConcurrentList<DatItem> keepDatItems = new ConcurrentList<DatItem>();
|
||||
foreach (DatItem datItem in datItems)
|
||||
{
|
||||
if (!datFile.Items.HasDuplicates(datItem, true))
|
||||
@@ -288,7 +288,7 @@ namespace SabreTools.DatTools
|
||||
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
ConcurrentList<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
|
||||
// If the rom list is empty or null, just skip it
|
||||
if (items == null || items.Count == 0)
|
||||
@@ -366,7 +366,7 @@ namespace SabreTools.DatTools
|
||||
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
ConcurrentList<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
|
||||
// If the rom list is empty or null, just skip it
|
||||
if (items == null || items.Count == 0)
|
||||
@@ -429,7 +429,7 @@ namespace SabreTools.DatTools
|
||||
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
ConcurrentList<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
|
||||
// If the rom list is empty or null, just skip it
|
||||
if (items == null || items.Count == 0)
|
||||
@@ -534,7 +534,7 @@ namespace SabreTools.DatTools
|
||||
// Loop through and add the items for this index to the output
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
ConcurrentList<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
|
||||
// If the rom list is empty or null, just skip it
|
||||
if (items == null || items.Count == 0)
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace SabreTools.DatTools
|
||||
return false;
|
||||
|
||||
// If either we have duplicates or we're filtering
|
||||
if (ShouldRebuild(datFile, datItem, fileStream, inverse, out List<DatItem> dupes))
|
||||
if (ShouldRebuild(datFile, datItem, fileStream, inverse, out ConcurrentList<DatItem> dupes))
|
||||
{
|
||||
// If we have a very specific TGZ->TGZ case, just copy it accordingly
|
||||
if (RebuildTorrentGzip(datFile, datItem, file, outDir, outputFormat, isZip))
|
||||
@@ -480,7 +480,7 @@ namespace SabreTools.DatTools
|
||||
/// <param name="inverse">True if the DAT should be used as a filter instead of a template, false otherwise</param>
|
||||
/// <param name="dupes">Output list of duplicate items to rebuild to</param>
|
||||
/// <returns>True if the item should be rebuilt, false otherwise</returns>
|
||||
private static bool ShouldRebuild(DatFile datFile, DatItem datItem, Stream stream, bool inverse, out List<DatItem> dupes)
|
||||
private static bool ShouldRebuild(DatFile datFile, DatItem datItem, Stream stream, bool inverse, out ConcurrentList<DatItem> dupes)
|
||||
{
|
||||
// Find if the file has duplicates in the DAT
|
||||
dupes = datFile.Items.GetDuplicates(datItem);
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace SabreTools.DatTools
|
||||
// Now separate the roms accordingly
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
if (newExtA.Contains((item.GetName() ?? string.Empty).GetNormalizedExtension()))
|
||||
@@ -147,7 +147,7 @@ namespace SabreTools.DatTools
|
||||
// Now populate each of the DAT objects in turn
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// If the file is not a Disk, Media, or Rom, continue
|
||||
@@ -248,7 +248,7 @@ namespace SabreTools.DatTools
|
||||
}
|
||||
|
||||
// Clean the input list and set all games to be pathless
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
items.ForEach(item => item.Machine.Name = Path.GetFileName(item.Machine.Name));
|
||||
items.ForEach(item => item.Machine.Description = Path.GetFileName(item.Machine.Description));
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace SabreTools.DatTools
|
||||
// Now populate each of the DAT objects in turn
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// If the file is not a Rom, it automatically goes in the "lesser" dat
|
||||
@@ -504,7 +504,7 @@ namespace SabreTools.DatTools
|
||||
// Loop through and add the items for this index to the output
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
ConcurrentList<DatItem> items = DatItem.Merge(datFile.Items[key]);
|
||||
|
||||
// If the rom list is empty or null, just skip it
|
||||
if (items == null || items.Count == 0)
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace SabreTools.DatTools
|
||||
var keys = datFile.Items.SortedKeys.ToList();
|
||||
foreach (string key in keys)
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
// Unmatched items will have a source ID of int.MaxValue, remove all others
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace SabreTools.Filtering
|
||||
foreach (string key in keys)
|
||||
{
|
||||
// For every item in the current key
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// If we have a null item, we can't clean it it
|
||||
@@ -250,7 +250,7 @@ namespace SabreTools.Filtering
|
||||
ConcurrentDictionary<string, string> mapping = new ConcurrentDictionary<string, string>();
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// If the key mapping doesn't exist, add it
|
||||
@@ -261,8 +261,8 @@ namespace SabreTools.Filtering
|
||||
// Now we loop through every item and update accordingly
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
List<DatItem> newItems = new List<DatItem>();
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> newItems = new ConcurrentList<DatItem>();
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// Update machine name
|
||||
@@ -543,7 +543,7 @@ namespace SabreTools.Filtering
|
||||
// For each rom, we want to update the game to be "<game name>/<rom name>"
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
SetOneRomPerGame(items[i]);
|
||||
@@ -580,7 +580,7 @@ namespace SabreTools.Filtering
|
||||
// Now process all of the roms
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
for (int j = 0; j < items.Count; j++)
|
||||
{
|
||||
DatItem item = items[j];
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace SabreTools.Filtering
|
||||
continue;
|
||||
|
||||
// Get the list of DatItems for the machine
|
||||
List<DatItem> datItems = datFile.Items[machine];
|
||||
ConcurrentList<DatItem> datItems = datFile.Items[machine];
|
||||
|
||||
// Try to get the map values, if possible
|
||||
combinedMachineMaps.TryGetValue(machine, out Dictionary<MachineField, string> machineMappings);
|
||||
|
||||
@@ -396,7 +396,7 @@ namespace SabreTools.Filtering
|
||||
{
|
||||
// For every item in the current key
|
||||
bool machinePass = true;
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// If we have a null item, we can't pass it
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace SabreTools.Filtering
|
||||
{
|
||||
Parallel.ForEach(datFile.Items.Keys, Globals.ParallelOptions, key =>
|
||||
{
|
||||
List<DatItem> items = datFile.Items[key];
|
||||
ConcurrentList<DatItem> items = datFile.Items[key];
|
||||
for (int j = 0; j < items.Count; j++)
|
||||
{
|
||||
DatItemRemover.RemoveFields(items[j]);
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace SabreTools.Filtering
|
||||
|
||||
// If the parent exists and has items, we copy the items from the parent to the current game
|
||||
DatItem copyFrom = datFile.Items[game][0];
|
||||
List<DatItem> parentItems = datFile.Items[parent];
|
||||
ConcurrentList<DatItem> parentItems = datFile.Items[parent];
|
||||
foreach (DatItem item in parentItems)
|
||||
{
|
||||
DatItem datItem = (DatItem)item.Clone();
|
||||
@@ -288,7 +288,7 @@ namespace SabreTools.Filtering
|
||||
continue;
|
||||
|
||||
// Add to the list of new device reference names
|
||||
List<DatItem> devItems = datFile.Items[deviceReference];
|
||||
ConcurrentList<DatItem> devItems = datFile.Items[deviceReference];
|
||||
newDeviceReferences.AddRange(devItems
|
||||
.Where(i => i.ItemType == ItemType.DeviceReference)
|
||||
.Select(i => (i as DeviceReference).Name));
|
||||
@@ -331,7 +331,7 @@ namespace SabreTools.Filtering
|
||||
continue;
|
||||
|
||||
// Add to the list of new slot option names
|
||||
List<DatItem> slotItems = datFile.Items[slotOption];
|
||||
ConcurrentList<DatItem> slotItems = datFile.Items[slotOption];
|
||||
newSlotOptions.AddRange(slotItems
|
||||
.Where(i => i.ItemType == ItemType.Slot)
|
||||
.Where(s => (s as Slot).SlotOptionsSpecified)
|
||||
@@ -396,7 +396,7 @@ namespace SabreTools.Filtering
|
||||
|
||||
// If the parent exists and has items, we copy the items from the parent to the current game
|
||||
DatItem copyFrom = datFile.Items[game][0];
|
||||
List<DatItem> parentItems = datFile.Items[parent];
|
||||
ConcurrentList<DatItem> parentItems = datFile.Items[parent];
|
||||
foreach (DatItem item in parentItems)
|
||||
{
|
||||
DatItem datItem = (DatItem)item.Clone();
|
||||
@@ -409,7 +409,7 @@ namespace SabreTools.Filtering
|
||||
}
|
||||
|
||||
// Now we want to get the parent romof tag and put it in each of the items
|
||||
List<DatItem> items = datFile.Items[game];
|
||||
ConcurrentList<DatItem> items = datFile.Items[game];
|
||||
string romof = datFile.Items[parent][0].Machine.RomOf;
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
@@ -454,7 +454,7 @@ namespace SabreTools.Filtering
|
||||
copyFrom = datFile.Items[parent][0];
|
||||
}
|
||||
|
||||
List<DatItem> items = datFile.Items[game];
|
||||
ConcurrentList<DatItem> items = datFile.Items[game];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
// Special disk handling
|
||||
@@ -582,7 +582,7 @@ namespace SabreTools.Filtering
|
||||
continue;
|
||||
|
||||
// If the parent exists and has items, we remove the items that are in the parent from the current game
|
||||
List<DatItem> parentItems = datFile.Items[parent];
|
||||
ConcurrentList<DatItem> parentItems = datFile.Items[parent];
|
||||
foreach (DatItem item in parentItems)
|
||||
{
|
||||
DatItem datItem = (DatItem)item.Clone();
|
||||
@@ -621,7 +621,7 @@ namespace SabreTools.Filtering
|
||||
continue;
|
||||
|
||||
// If the parent exists and has items, we remove the parent items from the current game
|
||||
List<DatItem> parentItems = datFile.Items[parent];
|
||||
ConcurrentList<DatItem> parentItems = datFile.Items[parent];
|
||||
foreach (DatItem item in parentItems)
|
||||
{
|
||||
DatItem datItem = (DatItem)item.Clone();
|
||||
@@ -632,7 +632,7 @@ namespace SabreTools.Filtering
|
||||
}
|
||||
|
||||
// Now we want to get the parent romof tag and put it in each of the remaining items
|
||||
List<DatItem> items = datFile.Items[game];
|
||||
ConcurrentList<DatItem> items = datFile.Items[game];
|
||||
string romof = datFile.Items[parent][0].Machine.RomOf;
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
@@ -650,7 +650,7 @@ namespace SabreTools.Filtering
|
||||
List<string> games = datFile.Items.Keys.OrderBy(g => g).ToList();
|
||||
foreach (string game in games)
|
||||
{
|
||||
List<DatItem> items = datFile.Items[game];
|
||||
ConcurrentList<DatItem> items = datFile.Items[game];
|
||||
foreach (DatItem item in items)
|
||||
{
|
||||
item.Machine.CloneOf = null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using SabreTools.Core;
|
||||
using SabreTools.DatFiles;
|
||||
using SabreTools.DatItems;
|
||||
using SabreTools.DatItems.Formats;
|
||||
@@ -19,7 +20,7 @@ namespace SabreTools.Test.DatFiles
|
||||
// Setup the dictionary
|
||||
var dict = new ItemDictionary
|
||||
{
|
||||
["game-1"] = new List<DatItem>
|
||||
["game-1"] = new ConcurrentList<DatItem>
|
||||
{
|
||||
new Rom
|
||||
{
|
||||
@@ -38,7 +39,7 @@ namespace SabreTools.Test.DatFiles
|
||||
Machine = new Machine { Name = "game-1" },
|
||||
},
|
||||
},
|
||||
["game-2"] = new List<DatItem>
|
||||
["game-2"] = new ConcurrentList<DatItem>
|
||||
{
|
||||
new Rom
|
||||
{
|
||||
@@ -69,8 +70,8 @@ namespace SabreTools.Test.DatFiles
|
||||
// Setup the dictionary
|
||||
var dict = new ItemDictionary
|
||||
{
|
||||
["game-1"] = new List<DatItem> { new Rom(), },
|
||||
["game-2"] = new List<DatItem>(),
|
||||
["game-1"] = new ConcurrentList<DatItem> { new Rom(), },
|
||||
["game-2"] = new ConcurrentList<DatItem>(),
|
||||
["game-3"] = null,
|
||||
};
|
||||
|
||||
@@ -84,7 +85,7 @@ namespace SabreTools.Test.DatFiles
|
||||
// Setup the dictionary
|
||||
var dict = new ItemDictionary
|
||||
{
|
||||
["game-1"] = new List<DatItem>
|
||||
["game-1"] = new ConcurrentList<DatItem>
|
||||
{
|
||||
new Rom
|
||||
{
|
||||
@@ -119,7 +120,7 @@ namespace SabreTools.Test.DatFiles
|
||||
// Setup the dictionary
|
||||
var dict = new ItemDictionary
|
||||
{
|
||||
["game-1"] = new List<DatItem>
|
||||
["game-1"] = new ConcurrentList<DatItem>
|
||||
{
|
||||
new Rom
|
||||
{
|
||||
@@ -158,7 +159,7 @@ namespace SabreTools.Test.DatFiles
|
||||
// Setup the dictionary
|
||||
var dict = new ItemDictionary
|
||||
{
|
||||
["game-1"] = new List<DatItem>
|
||||
["game-1"] = new ConcurrentList<DatItem>
|
||||
{
|
||||
new Rom
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user