Created
September 3, 2021 03:57
-
-
Save ShimmyMySherbet/18caede7a035ac6d48db6128f85f9149 to your computer and use it in GitHub Desktop.
A thread helper for Unturned Rocketmod with support for async calling between game thread and thread pool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Rocket.Core.Utils; | |
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace ShimmyMySherbet.Extensions | |
{ | |
/// <summary> | |
/// A collection of embedded tools to help manage threading and async operations | |
/// </summary> | |
public static class ThreadTool | |
{ | |
public delegate void VoidPattern(); | |
public delegate void VoidPattern<A>(A arg1); | |
public delegate void VoidPattern<A, B>(A arg1, B arg2); | |
public delegate void VoidPattern<A, B, C>(A arg1, B arg2, C arg3); | |
public delegate void VoidPattern<A, B, C, D>(A arg1, B arg2, C arg3, D arg4); | |
public delegate void VoidPattern<A, B, C, D, E>(A arg1, B arg2, C arg3, D arg4, E arg5); | |
public delegate Task TaskPattern(); | |
public delegate Task TaskPattern<A>(A arg1); | |
public delegate Task TaskPattern<A, B>(A arg1, B arg2); | |
public delegate Task TaskPattern<A, B, C>(A arg1, B arg2, C arg3); | |
public delegate Task TaskPattern<A, B, C, D>(A arg1, B arg2, C arg3, D arg4); | |
public delegate Task TaskPattern<A, B, C, D, E>(A arg1, B arg2, C arg3, D arg4, E arg5); | |
public delegate T FuncPattern<T>(); | |
public delegate T FuncPattern<T, A>(A arg1); | |
public delegate T FuncPattern<T, A, B>(A arg1, B arg2); | |
public delegate T FuncPattern<T, A, B, C>(A arg1, B arg2, C arg3); | |
public delegate T FuncPattern<T, A, B, C, D>(A arg1, B arg2, C arg3, D arg4); | |
public delegate T FuncPattern<T, A, B, C, D, E>(A arg1, B arg2, C arg3, D arg4, E arg5); | |
public static async Task RunOnGameThreadAsync(VoidPattern action) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task RunOnGameThreadAsync<A>(VoidPattern<A> action, A arg1) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(arg1); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task RunOnGameThreadAsync<A, B>(VoidPattern<A, B> action, A arg1, B arg2) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(arg1, arg2); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task RunOnGameThreadAsync<A, B, C>(VoidPattern<A, B, C> action, A arg1, B arg2, C arg3) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(arg1, arg2, arg3); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task RunOnGameThreadAsync<A, B, C, D>(VoidPattern<A, B, C, D> action, A arg1, B arg2, C arg3, D arg4) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(arg1, arg2, arg3, arg4); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task RunOnGameThreadAsync<A, B, C, D, E>(VoidPattern<A, B, C, D, E> action, A arg1, B arg2, C arg3, D arg4, E arg5) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
action(arg1, arg2, arg3, arg4, arg5); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
} | |
public static async Task<T> RunOnGameThreadAsync<T>(FuncPattern<T> action) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static async Task<T> RunOnGameThreadAsync<T, A>(FuncPattern<T, A> action, A arg1) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(arg1); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static async Task<T> RunOnGameThreadAsync<T, A, B>(FuncPattern<T, A, B> action, A arg1, B arg2) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(arg1, arg2); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static async Task<T> RunOnGameThreadAsync<T, A, B, C>(FuncPattern<T, A, B, C> action, A arg1, B arg2, C arg3) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(arg1, arg2, arg3); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static async Task<T> RunOnGameThreadAsync<T, A, B, C, D>(FuncPattern<T, A, B, C, D> action, A arg1, B arg2, C arg3, D arg4) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(arg1, arg2, arg3, arg4); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static async Task<T> RunOnGameThreadAsync<T, A, B, C, D, E>(FuncPattern<T, A, B, C, D, E> action, A arg1, B arg2, C arg3, D arg4, E arg5) | |
{ | |
var callback = new TaskCompletionSource<Exception>(); | |
T argue = default(T); | |
TaskDispatcher.QueueOnMainThread(() => | |
{ | |
try | |
{ | |
argue = action(arg1, arg2, arg3, arg4, arg5); | |
callback.SetResult(null); | |
} | |
catch (Exception ex) | |
{ | |
callback.SetResult(ex); | |
} | |
}); | |
var err = await callback.Task; | |
if (err != null) | |
{ | |
throw err; | |
} | |
return argue; | |
} | |
public static void QueueOnThreadPool(TaskPattern task) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task()); | |
} | |
public static void QueueOnThreadPool<A>(TaskPattern<A> task, A arg1) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task(arg1)); | |
} | |
public static void QueueOnThreadPool<A, B>(TaskPattern<A, B> task, A arg1, B arg2) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task(arg1, arg2)); | |
} | |
public static void QueueOnThreadPool<A, B, C>(TaskPattern<A, B, C> task, A arg1, B arg2, C arg3) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task(arg1, arg2, arg3)); | |
} | |
public static void QueueOnThreadPool<A, B, C, D>(TaskPattern<A, B, C, D> task, A arg1, B arg2, C arg3, D arg4) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task(arg1, arg2, arg3, arg4)); | |
} | |
public static void QueueOnThreadPool<A, B, C, D, E>(TaskPattern<A, B, C, D, E> task, A arg1, B arg2, C arg3, D arg4, E arg5) | |
{ | |
ThreadPool.QueueUserWorkItem(async (_) => await task(arg1, arg2, arg3, arg4, arg5)); | |
} | |
public static void QueueOnThreadPool(VoidPattern task) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task()); | |
} | |
public static void QueueOnThreadPool<A>(VoidPattern<A> task, A arg1) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task(arg1)); | |
} | |
public static void QueueOnThreadPool<A, B>(VoidPattern<A, B> task, A arg1, B arg2) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task(arg1, arg2)); | |
} | |
public static void QueueOnThreadPool<A, B, C>(VoidPattern<A, B, C> task, A arg1, B arg2, C arg3) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task(arg1, arg2, arg3)); | |
} | |
public static void QueueOnThreadPool<A, B, C, D>(VoidPattern<A, B, C, D> task, A arg1, B arg2, C arg3, D arg4) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task(arg1, arg2, arg3, arg4)); | |
} | |
public static void QueueOnThreadPool<A, B, C, D, E>(VoidPattern<A, B, C, D, E> task, A arg1, B arg2, C arg3, D arg4, E arg5) | |
{ | |
ThreadPool.QueueUserWorkItem((_) => task(arg1, arg2, arg3, arg4, arg5)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
looks cool, but, unitask and AsyncHelper in OpenMod is a good alternatives, in case you don't want to copy a lot of stuff