diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj
index bbf2e3b..c3d2823 100644
--- a/Torch.API/Torch.API.csproj
+++ b/Torch.API/Torch.API.csproj
@@ -163,10 +163,14 @@
+
+
+
+
diff --git a/Torch/Managers/Event/EventManager.cs b/Torch/Managers/Event/EventManager.cs
index 2c54a4b..f6b0330 100644
--- a/Torch/Managers/Event/EventManager.cs
+++ b/Torch/Managers/Event/EventManager.cs
@@ -39,7 +39,12 @@ namespace Torch.Managers.Event
}
}
- ///
+
+ ///
+ /// Gets all event handler methods declared by the given type and its base types.
+ ///
+ /// Type to explore
+ /// All event handler methods
private static IEnumerable EventHandlers(Type exploreType)
{
IEnumerable 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.
///
/// Assembly to unregister
- /// Optional callback invoked for every registered handler in the assembly. Ignored if null
+ /// Optional callback invoked before a handler is unregistered. Ignored if null
/// the number of handlers that were unregistered
- internal int UnregisterAllHandlers(Assembly asm, Func callback = null)
+ internal int UnregisterAllHandlers(Assembly asm, Action 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;
diff --git a/Torch/Managers/PatchManager/PatchContext.cs b/Torch/Managers/PatchManager/PatchContext.cs
index a213d99..66694a3 100644
--- a/Torch/Managers/PatchManager/PatchContext.cs
+++ b/Torch/Managers/PatchManager/PatchContext.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
namespace Torch.Managers.PatchManager
@@ -30,7 +31,17 @@ namespace Torch.Managers.PatchManager
_rewritePatterns.Add(method, res);
return res;
}
+
+ ///
+ /// Gets all methods that this context has patched
+ ///
+ internal IEnumerable PatchedMethods => _rewritePatterns
+ .Where(x => x.Value.Prefixes.Count > 0 || x.Value.Suffixes.Count > 0 || x.Value.Transpilers.Count > 0)
+ .Select(x => x.Key);
+ ///
+ /// Removes all patches in this context
+ ///
internal void RemoveAll()
{
foreach (MethodRewritePattern pattern in _rewritePatterns.Values)
diff --git a/Torch/Managers/PatchManager/PatchManager.cs b/Torch/Managers/PatchManager/PatchManager.cs
index 86b0905..7e9a205 100644
--- a/Torch/Managers/PatchManager/PatchManager.cs
+++ b/Torch/Managers/PatchManager/PatchManager.cs
@@ -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 _rewritePatterns = new Dictionary();
- private readonly HashSet _contexts = new HashSet();
+ private static readonly Dictionary _rewritePatterns = new Dictionary();
+ private readonly Dictionary> _contexts = new Dictionary>();
///
/// Gets the rewrite pattern for the given method, creating one if it doesn't exist.
@@ -27,21 +30,31 @@ namespace Torch.Managers.PatchManager
///
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;
+ }
}
///
/// Creates a new used for tracking changes. A call to will apply the patches.
///
+ [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 localContexts))
+ _contexts.Add(assembly, localContexts = new List());
+ 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 will apply the unpatching operation.
///
/// Context to remove
+ [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 localContexts))
+ localContexts.Remove(context);
+ }
+ }
+
+ ///
+ /// Frees all contexts owned by the given assembly. A call to will apply the unpatching operation.
+ ///
+ /// Assembly to retrieve owned contexts for
+ /// Callback to run for before each context is freed, ignored if null.
+ /// number of contexts freed
+ internal int FreeAllContexts(Assembly assembly, Action callback = null)
+ {
+ List 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;
}
///
@@ -80,7 +126,8 @@ namespace Torch.Managers.PatchManager
foreach (DecoratedMethod m in _rewritePatterns.Values)
m.Revert();
_rewritePatterns.Clear();
- _contexts.Clear();
+ lock (_contexts)
+ _contexts.Clear();
}
}
}
diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj
index 3fb3a01..a39572e 100644
--- a/Torch/Torch.csproj
+++ b/Torch/Torch.csproj
@@ -160,12 +160,10 @@
-
-
-
-
-
-
+
+
+
+