Patch manager state is static, registration methods are non-static.
Patch manager tracks patch context ownership by assembly internally
This commit is contained in:
@@ -163,10 +163,14 @@
|
||||
<Compile Include="ITorchConfig.cs" />
|
||||
<Compile Include="Managers\DependencyManagerExtensions.cs" />
|
||||
<Compile Include="Managers\DependencyProviderExtensions.cs" />
|
||||
<Compile Include="Managers\Event\EventHandlerAttribute.cs" />
|
||||
<Compile Include="Managers\Event\IEvent.cs" />
|
||||
<Compile Include="Managers\Event\IEventHandler.cs" />
|
||||
<Compile Include="Managers\IChatManagerClient.cs" />
|
||||
<Compile Include="Managers\IChatManagerServer.cs" />
|
||||
<Compile Include="Managers\IDependencyManager.cs" />
|
||||
<Compile Include="Managers\IDependencyProvider.cs" />
|
||||
<Compile Include="Managers\Event\IEventManager.cs" />
|
||||
<Compile Include="Managers\IManager.cs" />
|
||||
<Compile Include="Managers\IMultiplayerManagerClient.cs" />
|
||||
<Compile Include="Managers\IMultiplayerManagerBase.cs" />
|
||||
|
@@ -39,7 +39,12 @@ namespace Torch.Managers.Event
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
/// <summary>
|
||||
/// Gets all event handler methods declared by the given type and its base types.
|
||||
/// </summary>
|
||||
/// <param name="exploreType">Type to explore</param>
|
||||
/// <returns>All event handler methods</returns>
|
||||
private static IEnumerable<MethodInfo> EventHandlers(Type exploreType)
|
||||
{
|
||||
IEnumerable<MethodInfo> enumerable = exploreType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
||||
@@ -149,9 +154,9 @@ namespace Torch.Managers.Event
|
||||
/// Unregisters all handlers owned by the given assembly.
|
||||
/// </summary>
|
||||
/// <param name="asm">Assembly to unregister</param>
|
||||
/// <param name="callback">Optional callback invoked for every registered handler in the assembly. Ignored if null</param>
|
||||
/// <param name="callback">Optional callback invoked before a handler is unregistered. Ignored if null</param>
|
||||
/// <returns>the number of handlers that were unregistered</returns>
|
||||
internal int UnregisterAllHandlers(Assembly asm, Func<IEventHandler> callback = null)
|
||||
internal int UnregisterAllHandlers(Assembly asm, Action<IEventHandler> callback = null)
|
||||
{
|
||||
lock (_registeredHandlers)
|
||||
{
|
||||
@@ -159,7 +164,7 @@ namespace Torch.Managers.Event
|
||||
return 0;
|
||||
foreach (IEventHandler k in handlers)
|
||||
{
|
||||
callback?.Invoke();
|
||||
callback?.Invoke(k);
|
||||
UnregisterHandlerInternal(k);
|
||||
}
|
||||
int count = handlers.Count;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Torch.Managers.PatchManager
|
||||
@@ -31,6 +32,16 @@ namespace Torch.Managers.PatchManager
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all methods that this context has patched
|
||||
/// </summary>
|
||||
internal IEnumerable<MethodBase> PatchedMethods => _rewritePatterns
|
||||
.Where(x => x.Value.Prefixes.Count > 0 || x.Value.Suffixes.Count > 0 || x.Value.Transpilers.Count > 0)
|
||||
.Select(x => x.Key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all patches in this context
|
||||
/// </summary>
|
||||
internal void RemoveAll()
|
||||
{
|
||||
foreach (MethodRewritePattern pattern in _rewritePatterns.Values)
|
||||
|
@@ -1,6 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Torch.API;
|
||||
using Torch.Managers.PatchManager.Transpile;
|
||||
|
||||
namespace Torch.Managers.PatchManager
|
||||
{
|
||||
@@ -17,8 +20,8 @@ namespace Torch.Managers.PatchManager
|
||||
{
|
||||
}
|
||||
|
||||
private readonly Dictionary<MethodBase, DecoratedMethod> _rewritePatterns = new Dictionary<MethodBase, DecoratedMethod>();
|
||||
private readonly HashSet<PatchContext> _contexts = new HashSet<PatchContext>();
|
||||
private static readonly Dictionary<MethodBase, DecoratedMethod> _rewritePatterns = new Dictionary<MethodBase, DecoratedMethod>();
|
||||
private readonly Dictionary<Assembly, List<PatchContext>> _contexts = new Dictionary<Assembly, List<PatchContext>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rewrite pattern for the given method, creating one if it doesn't exist.
|
||||
@@ -27,21 +30,31 @@ namespace Torch.Managers.PatchManager
|
||||
/// <returns></returns>
|
||||
public MethodRewritePattern GetPattern(MethodBase method)
|
||||
{
|
||||
if (_rewritePatterns.TryGetValue(method, out DecoratedMethod pattern))
|
||||
return pattern;
|
||||
var res = new DecoratedMethod(method);
|
||||
_rewritePatterns.Add(method, res);
|
||||
return res;
|
||||
lock (_rewritePatterns)
|
||||
{
|
||||
if (_rewritePatterns.TryGetValue(method, out DecoratedMethod pattern))
|
||||
return pattern;
|
||||
var res = new DecoratedMethod(method);
|
||||
_rewritePatterns.Add(method, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="PatchContext"/> used for tracking changes. A call to <see cref="Commit"/> will apply the patches.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public PatchContext AcquireContext()
|
||||
{
|
||||
Assembly assembly = Assembly.GetCallingAssembly();
|
||||
var context = new PatchContext(this);
|
||||
_contexts.Add(context);
|
||||
lock (_contexts)
|
||||
{
|
||||
if (!_contexts.TryGetValue(assembly, out List<PatchContext> localContexts))
|
||||
_contexts.Add(assembly, localContexts = new List<PatchContext>());
|
||||
localContexts.Add(context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -49,10 +62,43 @@ namespace Torch.Managers.PatchManager
|
||||
/// Frees the given context, and unregister all patches from it. A call to <see cref="Commit"/> will apply the unpatching operation.
|
||||
/// </summary>
|
||||
/// <param name="context">Context to remove</param>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public void FreeContext(PatchContext context)
|
||||
{
|
||||
Assembly assembly = Assembly.GetCallingAssembly();
|
||||
context.RemoveAll();
|
||||
_contexts.Remove(context);
|
||||
lock (_contexts)
|
||||
{
|
||||
if (_contexts.TryGetValue(assembly, out List<PatchContext> localContexts))
|
||||
localContexts.Remove(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees all contexts owned by the given assembly. A call to <see cref="Commit"/> will apply the unpatching operation.
|
||||
/// </summary>
|
||||
/// <param name="assembly">Assembly to retrieve owned contexts for</param>
|
||||
/// <param name="callback">Callback to run for before each context is freed, ignored if null.</param>
|
||||
/// <returns>number of contexts freed</returns>
|
||||
internal int FreeAllContexts(Assembly assembly, Action<PatchContext> callback = null)
|
||||
{
|
||||
List<PatchContext> localContexts;
|
||||
lock (_contexts)
|
||||
{
|
||||
if (!_contexts.TryGetValue(assembly, out localContexts))
|
||||
return 0;
|
||||
_contexts.Remove(assembly);
|
||||
}
|
||||
if (localContexts == null)
|
||||
return 0;
|
||||
int count = localContexts.Count;
|
||||
foreach (PatchContext k in localContexts)
|
||||
{
|
||||
callback?.Invoke(k);
|
||||
k.RemoveAll();
|
||||
}
|
||||
localContexts.Clear();
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,7 +126,8 @@ namespace Torch.Managers.PatchManager
|
||||
foreach (DecoratedMethod m in _rewritePatterns.Values)
|
||||
m.Revert();
|
||||
_rewritePatterns.Clear();
|
||||
_contexts.Clear();
|
||||
lock (_contexts)
|
||||
_contexts.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -160,12 +160,10 @@
|
||||
<Compile Include="Extensions\DispatcherExtensions.cs" />
|
||||
<Compile Include="Extensions\ICollectionExtensions.cs" />
|
||||
<Compile Include="Managers\DependencyManager.cs" />
|
||||
<Compile Include="Managers\EventManager\EventHandlerAttribute.cs" />
|
||||
<Compile Include="Managers\EventManager\EventList.cs" />
|
||||
<Compile Include="Managers\EventManager\EventManager.cs" />
|
||||
<Compile Include="Managers\EventManager\EventShimProgrammableBlock.cs" />
|
||||
<Compile Include="Managers\EventManager\IEvent.cs" />
|
||||
<Compile Include="Managers\EventManager\IEventList.cs" />
|
||||
<Compile Include="Managers\Event\EventList.cs" />
|
||||
<Compile Include="Managers\Event\EventManager.cs" />
|
||||
<Compile Include="Managers\Event\EventShimProgrammableBlock.cs" />
|
||||
<Compile Include="Managers\Event\IEventList.cs" />
|
||||
<Compile Include="Managers\KeenLogManager.cs" />
|
||||
<Compile Include="Managers\PatchManager\AssemblyMemory.cs" />
|
||||
<Compile Include="Managers\PatchManager\DecoratedMethod.cs" />
|
||||
|
Reference in New Issue
Block a user