From 8a90e51a6207f31c828419ba3ad39cdb3395ecd9 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 20 Dec 2019 23:25:34 -0600 Subject: [PATCH] Moved the file information into a parameter to IConfigProvider's methods --- IPA.Loader/Config/Config.cs | 8 ++-- IPA.Loader/Config/ConfigRuntime.cs | 24 ++++------- IPA.Loader/Config/IConfigProvider.cs | 41 +++++++++++++------ IPA.Loader/Config/IConfigStore.cs | 4 +- .../Config/Providers/JsonConfigProvider.cs | 27 ++++++------ IPA.Loader/Config/Stores/GeneratedStore.cs | 8 ++-- 6 files changed, 62 insertions(+), 50 deletions(-) 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); {