Skip to content

Instantly share code, notes, and snippets.

@ShimmyMySherbet
Created September 3, 2021 03:57
Show Gist options
  • Save ShimmyMySherbet/18caede7a035ac6d48db6128f85f9149 to your computer and use it in GitHub Desktop.
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
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));
}
}
}
@sunnamed434
Copy link

looks cool, but, unitask and AsyncHelper in OpenMod is a good alternatives, in case you don't want to copy a lot of stuff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment