/AutoLazy

Post compile tool using Fody to implement the double check locking pattern.

Primary LanguageC#OtherNOASSERTION

AutoLazy

Post compile tool using Fody to implement the double-checked locking pattern.

The nuget package NuGet Status

https://nuget.org/packages/AutoLazy.Fody/

PM> Install-Package AutoLazy.Fody

Works on

  • static or instance members
  • parameterless methods
  • properties
  • methods with a single parameter (new)

Contributing

Please read the guidelines before submitting any changes. Thank you!

Example

Turns this

public class MyClass
{
	// This would work as a method, e.g. GetSettings(), as well.
	[Lazy]
	public static Settings Settings
	{
		get
		{
			using (var fs = File.Open("settings.xml", FileMode.Open))
			{
				var serializer = new XmlSerializer(typeof(Settings));
				return (Settings)serializer.Deserialize(fs);
			}
		}
	}

	[Lazy]
	public static Settings GetSettingsFile(string fileName)
	{
		using (var fs = File.Open(fileName, FileMode.Open))
		{
			var serializer = new XmlSerializer(typeof(Settings));
			return (Settings)serializer.Deserialize(fs);
		}
	}
}

Into something equivalent to this

public class MyClass
{
	// begin - fields added by the post-compile step
	private static readonly object _syncRoot = new object();
	private static volatile Settings _settings;
	// end
	
	[Lazy]
	public static Settings Settings
	{
		get
		{
			// thread-safe double-checked locking pattern generated here
			var result = _settings;
			if (result == null)
			{
				lock(_syncRoot)
				{
					result = _settings;
					if (result == null)
					{
						using (var fs = File.Open("settings.xml", FileMode.Open))
						{
							var serializer = new XmlSerializer(typeof(Settings));
							result = (Settings)serializer.Deserialize(fs);
							_settings = result;
						}
					}
				}
			}
			return result;
		}
	}

	// begin - fields added by post-compile step
	private static readonly object _getSettingsFileSyncRoot = new object();
	private static volatile Dictionary<string, Settings> _getSettingsFileCache
		= new Dictionary<string, Settings>();
	// end

	[Lazy]
	public static Settings GetSettingsFile(string fileName)
	{
		Settings result;
		if (!_getSettingsFileCache.TryGetValue(fileName, out result)) // volatile read
		{
			lock (_getSettingsFileSyncRoot)
			{
				if (!_getSettingsFileCache.TryGetValue(fileName, out result))
				{
					using (var fs = File.Open(fileName, FileMode.Open))
					{
						var serializer = new XmlSerializer(typeof(Settings));
						result = (Settings)serializer.Deserialize(fs);
					}
					// note - we can't mutate the dictionary after
					// exposing it to reads (possibly from other threads)
					// therefore, we have to copy the dictionary into a new one
					// then expose it by setting _getSettingsFileCache
					var newCache = new Dictionary<string, Settings>(_getSettingsFileCache.Count + 1);
					newCache.Add(fileName, result);
					foreach (var pair in _getSettingsFileCache)
					{
						newCache.Add(pair.Key, pair.Value);
					}
					_getSettingsFileCache = newCache; // volatile write
				}
			}
		}
		return result;
	}

}