# UnrealThread

<Badge tone="type">class · AR51SDK_API</Badge> <Badge>C++ only</Badge> <Badge>singleton</Badge>

```cpp
class AR51SDK_API UnrealThread   // hidden singleton: private ctor + Instance()
```

A **game-thread dispatcher**: it marshals work from worker/background threads onto the Unreal main (game) thread, where it is safe to touch `UObject`s and engine state. Implemented as a hidden singleton — you never construct it or reach for its instance directly; you call the static methods below.

This type is **C++ only** — none of its members are `UFUNCTION`s, so nothing here is reachable from Blueprint. It exists for SDK and advanced integration C++ code that runs off the game thread (e.g. a gRPC consume loop) and needs to hop back onto it.

Pick a method by what you need:

- **On the game thread already?** Guard with [`IsMainThread`](#ismainthread).
- **Need the result now, blocking?** [`Invoke`](#invoke) (synchronous).
- **Fire-and-forget, inspect later?** [`BeginInvoke`](#begininvoke) (asynchronous; returns a [task handle](#task-handles)).

:::caution[Units]
None of these methods carry positional/length values, so no cm↔m conversion applies here. (Unreal is centimeters/degrees; AR 51 mocap data is meters — conversion lives in the data/transform layer, not the threading utilities.)
:::

## Method summary

**Static — threading**

| Method | Returns | |
|---|---|---|
| [`IsMainThread`](#ismainthread) | `bool` | <Badge>C++ only</Badge> |
| [`Invoke`](#invoke) | `void` / `T` | <Badge>C++ only</Badge> · synchronous · overloads |
| [`BeginInvoke`](#begininvoke) | [`shared_ptr<TaskBase>`](#task-handles) / [`shared_ptr<Task<T>>`](#task-handles) | <Badge>C++ only</Badge> · asynchronous · overloads |

**Static — lifecycle** <Badge tone="warn">⚠️ likely internal</Badge>

| Method | Returns | |
|---|---|---|
| [`Tick` / `Start` / `Stop` / `Clear`](#lifecycle) | `void` | <Badge>C++ only</Badge> |

→ Full descriptions in [Method details](#method-details) below.

## Method details

### IsMainThread

<ApiBody kind="method" tags="static, C++ only">

```cpp
static bool IsMainThread();
```

Whether the calling code is currently running on the Unreal main/game thread.

<Returns type="bool">`true` if called from the game thread; `false` from any worker thread</Returns>

<Example inferred>

```cpp
// Skip the marshal cost when we're already on the game thread.
auto Apply = [Char]{ Char->ApplyOnSkeletalMeshes(); };
if (UnrealThread::IsMainThread())
    Apply();
else
    UnrealThread::Invoke(Apply, TEXT("ApplyPose"));
```

</Example>

</ApiBody>

### Invoke

<ApiBody kind="method" tags="static, C++ only, synchronous, overloads">

```cpp
// (1) void result — blocks until done
static void Invoke(const std::function<void()>& action,
                   const FString& name = "Untitled");

// (2) typed result — runs on the game thread, returns its value
template<typename T>
static T Invoke(const std::function<T()>& action,
                const FString& name = "Untitled");

// (3) typed result with cancellation fallback
template<typename T>
static T Invoke(const std::function<T()>& action,
                const T& canceledValue);
```

Schedules `action` on the main thread and **blocks the caller until it completes** (a synchronous marshal). Use this from a worker thread when you must safely read or mutate `UObject`s / engine state and need the call to finish — or its result returned — before continuing.

- **(1)** runs a `void` action and waits for it.
- **(2)** runs an action returning `T` and hands back its result.
- **(3)** same as (2) but, if the task is canceled (e.g. the dispatcher is not running), returns `canceledValue` instead of the action's result.

The optional `name` labels the queued task for diagnostics/logging.

<Params>
<Param name="action" type="std::function">the work to run on the game thread (returning `void` or `T`)</Param>
<Param name="name" type="FString">a label for the queued task (default `"Untitled"`)</Param>
<Param name="canceledValue" type="T">overload (3): value returned if the task is canceled</Param>
</Params>

<Returns type="void / T">nothing for (1); the action's result for (2); the result or `canceledValue` for (3)</Returns>

<Example inferred>

```cpp
// From a worker thread, read engine state synchronously and use the result.
const FVector Head = UnrealThread::Invoke<FVector>(
    [Char]{ return Char->GetHeadPosition(); },   // UE cm
    /*canceledValue*/ FVector::ZeroVector);
```

</Example>

:::caution
`Invoke` blocks. Never call it **from** the game thread waiting on the game thread — that deadlocks. Guard with [`IsMainThread`](#ismainthread) (run the work inline if already on the game thread).
:::

</ApiBody>

### BeginInvoke

<ApiBody kind="method" tags="static, C++ only, asynchronous, overloads">

```cpp
// (1) void result — returns an untyped handle
static std::shared_ptr<TaskBase> BeginInvoke(const std::function<void()>& action,
                                             const FString& name = "Untitled");

// (2) typed result — returns a typed handle carrying T
template<typename T>
static std::shared_ptr<Task<T>> BeginInvoke(const std::function<T()>& action,
                                            const FString& name = "Untitled");
```

Fire-and-forget **asynchronous** dispatch: queues `action` to run on the main thread and returns immediately with a [task handle](#task-handles) you can await or inspect later — `TaskBase` for the `void` overload, `Task<T>` for the typed one. If the dispatcher is not running, the typed overload returns an already-canceled task.

<Params>
<Param name="action" type="std::function">the work to run on the game thread (returning `void` or `T`)</Param>
<Param name="name" type="FString">a label for the queued task (default `"Untitled"`)</Param>
</Params>

<Returns type="shared_ptr<TaskBase> / shared_ptr<Task<T>>">a handle to await/inspect the queued work (see [Task handles](#task-handles))</Returns>

<Example inferred>

```cpp
// Queue work on the game thread without blocking; grab the result when ready.
auto Task = UnrealThread::BeginInvoke<int32>(
    [Consumer]{ return Consumer->GetCharacters().Num(); });

// ... later, on any thread:
Task->Wait();
if (Task->IsCompleted() && !Task->IsCanceled())
    const int32 Count = Task->GetResult();
```

</Example>

</ApiBody>

### Task handles

<ApiBody kind="property" tags="C++ only, return types">

```cpp
std::shared_ptr<TaskBase>   // returned by the void  BeginInvoke
std::shared_ptr<Task<T>>    // returned by the typed BeginInvoke
```

The lightweight handles returned by [`BeginInvoke`](#begininvoke). You **consume** these as return values; you do not construct them (their constructors and the `Run`/`Cancel` machinery are internal). Both expose:

- `bool IsCompleted()` — the task has finished running.
- `bool IsCanceled()` — the task was canceled (e.g. the dispatcher was not running) and never produced a result.
- `void Wait()` — block the caller until the task completes (or is canceled).
- `GetResult()` — on `Task<T>`, the action's `T` result (valid once completed and not canceled).

</ApiBody>

### Lifecycle

<ApiBody kind="method" tags="static, C++ only">

```cpp
static void Tick();    // drain + run queued tasks on the game thread
static void Start();   // enable processing
static void Stop();    // disable processing
static void Clear();   // empty the queue
```

Dispatcher pump / lifecycle controls. `Tick()` drains the queue and runs pending tasks on the main thread (typically once per frame); `Start`/`Stop` enable/disable processing; `Clear` empties the queue.

:::caution[⚠️ Likely internal]
The SDK is expected to pump these itself (e.g. driving `Tick()` from its per-frame loop). Integrators normally call only [`IsMainThread`](#ismainthread), [`Invoke`](#invoke), and [`BeginInvoke`](#begininvoke). Calling `Stop`/`Clear` from game code can strand or drop queued work. ⚠️ needs confirmation that any of these are intended for integrator use.
:::

</ApiBody>

## See also

- [`UNetworkUtils`](/docs/sdk-api/unreal-api/classes/unetworkutils) — the other game-dev-facing C++ utility helper (networking)
- [Utilities & Platform](/docs/sdk-api/unreal-api/utilities-platform) — platform enum, logging, singletons, and these threading helpers
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
