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="ITorchConfig.cs" />
|
||||||
<Compile Include="Managers\DependencyManagerExtensions.cs" />
|
<Compile Include="Managers\DependencyManagerExtensions.cs" />
|
||||||
<Compile Include="Managers\DependencyProviderExtensions.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\IChatManagerClient.cs" />
|
||||||
<Compile Include="Managers\IChatManagerServer.cs" />
|
<Compile Include="Managers\IChatManagerServer.cs" />
|
||||||
<Compile Include="Managers\IDependencyManager.cs" />
|
<Compile Include="Managers\IDependencyManager.cs" />
|
||||||
<Compile Include="Managers\IDependencyProvider.cs" />
|
<Compile Include="Managers\IDependencyProvider.cs" />
|
||||||
|
<Compile Include="Managers\Event\IEventManager.cs" />
|
||||||
<Compile Include="Managers\IManager.cs" />
|
<Compile Include="Managers\IManager.cs" />
|
||||||
<Compile Include="Managers\IMultiplayerManagerClient.cs" />
|
<Compile Include="Managers\IMultiplayerManagerClient.cs" />
|
||||||
<Compile Include="Managers\IMultiplayerManagerBase.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)
|
private static IEnumerable<MethodInfo> EventHandlers(Type exploreType)
|
||||||
{
|
{
|
||||||
IEnumerable<MethodInfo> enumerable = exploreType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
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.
|
/// Unregisters all handlers owned by the given assembly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asm">Assembly to unregister</param>
|
/// <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>
|
/// <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)
|
lock (_registeredHandlers)
|
||||||
{
|
{
|
||||||
@@ -159,7 +164,7 @@ namespace Torch.Managers.Event
|
|||||||
return 0;
|
return 0;
|
||||||
foreach (IEventHandler k in handlers)
|
foreach (IEventHandler k in handlers)
|
||||||
{
|
{
|
||||||
callback?.Invoke();
|
callback?.Invoke(k);
|
||||||
UnregisterHandlerInternal(k);
|
UnregisterHandlerInternal(k);
|
||||||
}
|
}
|
||||||
int count = handlers.Count;
|
int count = handlers.Count;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Torch.Managers.PatchManager
|
namespace Torch.Managers.PatchManager
|
||||||
@@ -31,6 +32,16 @@ namespace Torch.Managers.PatchManager
|
|||||||
return res;
|
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()
|
internal void RemoveAll()
|
||||||
{
|
{
|
||||||
foreach (MethodRewritePattern pattern in _rewritePatterns.Values)
|
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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
|
using Torch.Managers.PatchManager.Transpile;
|
||||||
|
|
||||||
namespace Torch.Managers.PatchManager
|
namespace Torch.Managers.PatchManager
|
||||||
{
|
{
|
||||||
@@ -17,8 +20,8 @@ namespace Torch.Managers.PatchManager
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<MethodBase, DecoratedMethod> _rewritePatterns = new Dictionary<MethodBase, DecoratedMethod>();
|
private static readonly Dictionary<MethodBase, DecoratedMethod> _rewritePatterns = new Dictionary<MethodBase, DecoratedMethod>();
|
||||||
private readonly HashSet<PatchContext> _contexts = new HashSet<PatchContext>();
|
private readonly Dictionary<Assembly, List<PatchContext>> _contexts = new Dictionary<Assembly, List<PatchContext>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the rewrite pattern for the given method, creating one if it doesn't exist.
|
/// 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>
|
/// <returns></returns>
|
||||||
public MethodRewritePattern GetPattern(MethodBase method)
|
public MethodRewritePattern GetPattern(MethodBase method)
|
||||||
{
|
{
|
||||||
if (_rewritePatterns.TryGetValue(method, out DecoratedMethod pattern))
|
lock (_rewritePatterns)
|
||||||
return pattern;
|
{
|
||||||
var res = new DecoratedMethod(method);
|
if (_rewritePatterns.TryGetValue(method, out DecoratedMethod pattern))
|
||||||
_rewritePatterns.Add(method, res);
|
return pattern;
|
||||||
return res;
|
var res = new DecoratedMethod(method);
|
||||||
|
_rewritePatterns.Add(method, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="PatchContext"/> used for tracking changes. A call to <see cref="Commit"/> will apply the patches.
|
/// Creates a new <see cref="PatchContext"/> used for tracking changes. A call to <see cref="Commit"/> will apply the patches.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
public PatchContext AcquireContext()
|
public PatchContext AcquireContext()
|
||||||
{
|
{
|
||||||
|
Assembly assembly = Assembly.GetCallingAssembly();
|
||||||
var context = new PatchContext(this);
|
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;
|
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.
|
/// Frees the given context, and unregister all patches from it. A call to <see cref="Commit"/> will apply the unpatching operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">Context to remove</param>
|
/// <param name="context">Context to remove</param>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
public void FreeContext(PatchContext context)
|
public void FreeContext(PatchContext context)
|
||||||
{
|
{
|
||||||
|
Assembly assembly = Assembly.GetCallingAssembly();
|
||||||
context.RemoveAll();
|
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>
|
/// <summary>
|
||||||
@@ -80,7 +126,8 @@ namespace Torch.Managers.PatchManager
|
|||||||
foreach (DecoratedMethod m in _rewritePatterns.Values)
|
foreach (DecoratedMethod m in _rewritePatterns.Values)
|
||||||
m.Revert();
|
m.Revert();
|
||||||
_rewritePatterns.Clear();
|
_rewritePatterns.Clear();
|
||||||
_contexts.Clear();
|
lock (_contexts)
|
||||||
|
_contexts.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -160,12 +160,10 @@
|
|||||||
<Compile Include="Extensions\DispatcherExtensions.cs" />
|
<Compile Include="Extensions\DispatcherExtensions.cs" />
|
||||||
<Compile Include="Extensions\ICollectionExtensions.cs" />
|
<Compile Include="Extensions\ICollectionExtensions.cs" />
|
||||||
<Compile Include="Managers\DependencyManager.cs" />
|
<Compile Include="Managers\DependencyManager.cs" />
|
||||||
<Compile Include="Managers\EventManager\EventHandlerAttribute.cs" />
|
<Compile Include="Managers\Event\EventList.cs" />
|
||||||
<Compile Include="Managers\EventManager\EventList.cs" />
|
<Compile Include="Managers\Event\EventManager.cs" />
|
||||||
<Compile Include="Managers\EventManager\EventManager.cs" />
|
<Compile Include="Managers\Event\EventShimProgrammableBlock.cs" />
|
||||||
<Compile Include="Managers\EventManager\EventShimProgrammableBlock.cs" />
|
<Compile Include="Managers\Event\IEventList.cs" />
|
||||||
<Compile Include="Managers\EventManager\IEvent.cs" />
|
|
||||||
<Compile Include="Managers\EventManager\IEventList.cs" />
|
|
||||||
<Compile Include="Managers\KeenLogManager.cs" />
|
<Compile Include="Managers\KeenLogManager.cs" />
|
||||||
<Compile Include="Managers\PatchManager\AssemblyMemory.cs" />
|
<Compile Include="Managers\PatchManager\AssemblyMemory.cs" />
|
||||||
<Compile Include="Managers\PatchManager\DecoratedMethod.cs" />
|
<Compile Include="Managers\PatchManager\DecoratedMethod.cs" />
|
||||||
|
Reference in New Issue
Block a user