Skip to content

Commit dc547fd

Browse files
authored
Add named worker queues (#112)
1 parent df42c28 commit dc547fd

1 file changed

Lines changed: 119 additions & 0 deletions

File tree

WorkerQueues.cs

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

0 commit comments

Comments
 (0)