diff --git a/IPA.Loader/Config/Config.cs b/IPA.Loader/Config/Config.cs
index e3860b9b..6d66174e 100644
--- a/IPA.Loader/Config/Config.cs
+++ b/IPA.Loader/Config/Config.cs
@@ -131,14 +131,15 @@ namespace IPA.Config
///
/// Gets the name associated with this object.
///
- public string Name { get; private set; }
+ public string Name { get; }
///
/// Gets the associated with this object.
///
- public IConfigProvider Provider { get; private set; }
+ public IConfigProvider Provider { get; }
internal IConfigStore Store = null;
internal readonly FileInfo File;
+ internal readonly ConfigProvider configProvider;
internal int Writes = 0;
///
@@ -166,7 +167,8 @@ namespace IPA.Config
private Config(string name, IConfigProvider provider, FileInfo file)
{
- Name = name; Provider = provider; File = file;
+ Name = name; Provider = provider; File = file;
+ configProvider = new ConfigProvider(file, provider);
}
}
}
diff --git a/IPA.Loader/Config/ConfigRuntime.cs b/IPA.Loader/Config/ConfigRuntime.cs
index 8266cfe9..e59d13a0 100644
--- a/IPA.Loader/Config/ConfigRuntime.cs
+++ b/IPA.Loader/Config/ConfigRuntime.cs
@@ -151,10 +151,11 @@ namespace IPA.Config
}
}
- public static Task TriggerFileLoad(Config config) => loadFactory.StartNew(() => LoadTask(config));
+ public static Task TriggerFileLoad(Config config)
+ => loadFactory.StartNew(() => LoadTask(config));
- public static Task TriggerLoadAll() =>
- TaskEx.WhenAll(configs.Select(TriggerFileLoad));
+ public static Task TriggerLoadAll()
+ => TaskEx.WhenAll(configs.Select(TriggerFileLoad));
///
/// this is synchronous, unlike
@@ -167,13 +168,10 @@ namespace IPA.Config
try
{
using var readLock = Synchronization.LockRead(store.WriteSyncObject);
- lock (config.Provider)
- {
- config.Provider.File = config.File;
- EnsureWritesSane(config);
- Interlocked.Increment(ref config.Writes);
- store.WriteTo(config.Provider);
- }
+
+ EnsureWritesSane(config);
+ Interlocked.Increment(ref config.Writes);
+ store.WriteTo(config.configProvider);
}
catch (ThreadAbortException)
{
@@ -201,11 +199,7 @@ namespace IPA.Config
{
var store = config.Store;
using var writeLock = Synchronization.LockWrite(store.WriteSyncObject);
- lock (config.Provider)
- {
- config.Provider.File = config.File;
- store.ReadFrom(config.Provider);
- }
+ store.ReadFrom(config.configProvider);
}
catch (Exception e)
{
diff --git a/IPA.Loader/Config/IConfigProvider.cs b/IPA.Loader/Config/IConfigProvider.cs
index aa7f28c9..5f52c398 100644
--- a/IPA.Loader/Config/IConfigProvider.cs
+++ b/IPA.Loader/Config/IConfigProvider.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Threading.Tasks;
using IPA.Config.Data;
namespace IPA.Config
@@ -32,30 +33,44 @@ namespace IPA.Config
string Extension { get; }
///
- /// Sets the file that this provider will read and write to.
+ /// Stores the given to disk in the format specified.
///
- ///
- /// The provider is expected to gracefully handle this changing at any point,
- /// and is expected to close any old file handles when this is reassigned.
- /// This may be set to the same file multiple times in this object's lifetime.
- /// This will always have been set at least once before any calls to
- /// or are made.
- ///
- FileInfo File { set; }
+ /// the to store
+ /// the file to write to
+ void Store(Value value, FileInfo file);
+
+ ///
+ /// Loads a from disk in whatever format this provider provides
+ /// and returns it.
+ ///
+ /// the file to read from
+ /// the loaded
+ Value Load(FileInfo file);
+ }
+
+ ///
+ /// A wrapper for an and the to use with it.
+ ///
+ public class ConfigProvider // this *should* be a struct imo, but mono doesn't seem to like that
+ {
+ private readonly FileInfo file;
+ private readonly IConfigProvider provider;
- // TODO: consider moving to asynchronous Store and Load with a FileInfo parameter
+ internal ConfigProvider(FileInfo file, IConfigProvider provider)
+ {
+ this.file = file; this.provider = provider;
+ }
///
/// Stores the given to disk in the format specified.
///
/// the to store
- void Store(Value value);
-
+ public void Store(Value value) => provider.Store(value, file);
///
/// Loads a from disk in whatever format this provider provides
/// and returns it.
///
/// the loaded
- Value Load();
+ public Value Load() => provider.Load(file);
}
}
diff --git a/IPA.Loader/Config/IConfigStore.cs b/IPA.Loader/Config/IConfigStore.cs
index 634617a0..240ecf04 100644
--- a/IPA.Loader/Config/IConfigStore.cs
+++ b/IPA.Loader/Config/IConfigStore.cs
@@ -40,7 +40,7 @@ namespace IPA.Config
/// this is called.
///
/// the provider to write to
- void WriteTo(IConfigProvider provider);
+ void WriteTo(ConfigProvider provider);
///
/// Reads the config structure from the given into the current
@@ -51,7 +51,7 @@ namespace IPA.Config
/// this is called.
///
/// the provider to read from
- void ReadFrom(IConfigProvider provider);
+ void ReadFrom(ConfigProvider provider);
}
}
diff --git a/IPA.Loader/Config/Providers/JsonConfigProvider.cs b/IPA.Loader/Config/Providers/JsonConfigProvider.cs
index 4336943e..dedec706 100644
--- a/IPA.Loader/Config/Providers/JsonConfigProvider.cs
+++ b/IPA.Loader/Config/Providers/JsonConfigProvider.cs
@@ -9,6 +9,7 @@ using System.ComponentModel;
using System.IO;
using System.Collections.Generic;
using Boolean = IPA.Config.Data.Boolean;
+using System.Threading.Tasks;
namespace IPA.Config.Providers
{
@@ -21,14 +22,12 @@ namespace IPA.Config.Providers
public string Extension => "json";
- public FileInfo File { get; set; }
-
- public Value Load()
+ public Value Load(FileInfo file)
{
- if (!File.Exists) return Value.Null();
+ if (!file.Exists) return Value.Null();
JToken jtok;
- using (var sreader = new StreamReader(File.OpenRead()))
+ using (var sreader = new StreamReader(file.OpenRead()))
{
using var jreader = new JsonTextReader(sreader);
jtok = JToken.ReadFrom(jreader);
@@ -40,7 +39,7 @@ namespace IPA.Config.Providers
}
catch (Exception e)
{
- Logger.config.Error($"Error reading JSON file {File.FullName}; ignoring");
+ Logger.config.Error($"Error reading JSON file {file.FullName}; ignoring");
Logger.config.Error(e);
return Value.Null();
}
@@ -116,23 +115,25 @@ namespace IPA.Config.Providers
}
}
- public void Store(Value value)
+ public void Store(Value value, FileInfo file)
{
- if (File.Directory.Exists)
- File.Directory.Create();
+ if (file.Directory.Exists)
+ file.Directory.Create();
try
{
var tok = VisitToToken(value);
- using var swriter = new StreamWriter(File.Open(FileMode.Create, FileAccess.Write));
- using var jwriter = new JsonTextWriter(swriter);
- jwriter.Formatting = Formatting.Indented;
+ using var swriter = new StreamWriter(file.Open(FileMode.Create, FileAccess.Write));
+ using var jwriter = new JsonTextWriter(swriter)
+ {
+ Formatting = Formatting.Indented
+ };
tok.WriteTo(jwriter);
}
catch (Exception e)
{
- Logger.config.Error($"Error serializing value for {File.FullName}");
+ Logger.config.Error($"Error serializing value for {file.FullName}");
Logger.config.Error(e);
}
}
diff --git a/IPA.Loader/Config/Stores/GeneratedStore.cs b/IPA.Loader/Config/Stores/GeneratedStore.cs
index a98112f1..5aa65a77 100644
--- a/IPA.Loader/Config/Stores/GeneratedStore.cs
+++ b/IPA.Loader/Config/Stores/GeneratedStore.cs
@@ -155,7 +155,7 @@ namespace IPA.Config.Stores
internal static MethodInfo ReadFromMethod = typeof(Impl).GetMethod(nameof(ReadFrom));
- public void ReadFrom(IConfigProvider provider)
+ public void ReadFrom(ConfigProvider provider)
{
var values = provider.Load();
Logger.config.Debug("Generated impl ReadFrom");
@@ -168,7 +168,7 @@ namespace IPA.Config.Stores
}
internal static MethodInfo WriteToMethod = typeof(Impl).GetMethod(nameof(WriteTo));
- public void WriteTo(IConfigProvider provider)
+ public void WriteTo(ConfigProvider provider)
{
var values = generated.Serialize();
Logger.config.Debug("Generated impl WriteTo");
@@ -714,7 +714,7 @@ namespace IPA.Config.Stores
}
#endregion
#region IConfigStore.WriteTo
- var writeTo = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.WriteTo)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
+ var writeTo = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.WriteTo)}", virtualMemberMethod, null, new[] { typeof(ConfigProvider) });
typeBuilder.DefineMethodOverride(writeTo, IConfigStore_WriteTo);
{
@@ -729,7 +729,7 @@ namespace IPA.Config.Stores
}
#endregion
#region IConfigStore.ReadFrom
- var readFrom = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.ReadFrom)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
+ var readFrom = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.ReadFrom)}", virtualMemberMethod, null, new[] { typeof(ConfigProvider) });
typeBuilder.DefineMethodOverride(readFrom, IConfigStore_ReadFrom);
{