-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathWorkerQueues.cs
More file actions
119 lines (108 loc) · 2.73 KB
/
Copy pathWorkerQueues.cs
File metadata and controls
119 lines (108 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Runtime.InteropServices;
namespace BinaryNinja
{
internal static partial class NativeDelegates
{
[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
internal delegate void BNWorkerAction(IntPtr context);
}
public static partial class Core
{
private enum WorkerQueueKind
{
Default,
Priority,
Interactive
}
private static readonly NativeDelegates.BNWorkerAction workerActionCallback =
new NativeDelegates.BNWorkerAction(Core.InvokeWorkerAction);
/// <summary>Enqueues a named action on the default analysis worker queue.</summary>
public static void WorkerEnqueue(Action action, string name = "")
{
Core.EnqueueWorker(WorkerQueueKind.Default, action, name);
}
/// <summary>Enqueues a named action ahead of normal analysis worker work.</summary>
public static void WorkerPriorityEnqueue(Action action, string name = "")
{
Core.EnqueueWorker(WorkerQueueKind.Priority, action, name);
}
/// <summary>Enqueues a named action on the interactive worker queue.</summary>
public static void WorkerInteractiveEnqueue(Action action, string name = "")
{
Core.EnqueueWorker(WorkerQueueKind.Interactive, action, name);
}
private static void EnqueueWorker(WorkerQueueKind kind, Action action, string name)
{
if (null == action)
{
throw new ArgumentNullException(nameof(action));
}
GCHandle context = GCHandle.Alloc(action);
IntPtr contextPointer = GCHandle.ToIntPtr(context);
IntPtr callback = Marshal.GetFunctionPointerForDelegate(
Core.workerActionCallback
);
try
{
switch (kind)
{
case WorkerQueueKind.Default:
NativeMethods.BNWorkerEnqueueNamed(
contextPointer,
callback,
name ?? string.Empty
);
break;
case WorkerQueueKind.Priority:
NativeMethods.BNWorkerPriorityEnqueueNamed(
contextPointer,
callback,
name ?? string.Empty
);
break;
case WorkerQueueKind.Interactive:
NativeMethods.BNWorkerInteractiveEnqueueNamed(
contextPointer,
callback,
name ?? string.Empty
);
break;
default:
throw new ArgumentOutOfRangeException(nameof(kind));
}
}
catch
{
if (context.IsAllocated)
{
context.Free();
}
throw;
}
}
private static void InvokeWorkerAction(IntPtr contextPointer)
{
GCHandle context = GCHandle.FromIntPtr(contextPointer);
try
{
Action? action = context.Target as Action;
if (null != action)
{
action();
}
}
catch (Exception exception)
{
Core.LogError("Unhandled exception in worker action: {0}", exception);
}
finally
{
if (context.IsAllocated)
{
context.Free();
}
}
}
}
}