UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VVMTask.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#if WITH_VERSE_VM || defined(__INTELLISENSE__)
6
9#include "VerseVM/VVMCell.h"
10#include "VerseVM/VVMClass.h"
11#include "VerseVM/VVMDebugger.h"
17#include "VerseVM/VVMTree.h"
20
21namespace Verse
22{
23struct FOp;
24struct VFailureContext;
25
26struct VTask : VValueObject
27 , TIntrusiveTree<VTask>
28{
31
32 // A task is "running" when it is associated with a frame on the native stack.
33 // This includes a running interpreter (even if it is just on the `YieldTask` chain), and native
34 // functions like `CancelChildren`.
35 // Running tasks can only be resumed by falling through a sequence of yields and native returns.
36 // This is independent of `Phase`, as both active and cancelling tasks may suspend.
37 bool bRunning{true};
38
39 // See the note on CancelImpl.
40 enum class EPhase : int8
41 {
42 Active,
47 };
48 EPhase Phase{EPhase::Active};
49
50 // The task group associated with this task.
52
53 // To be run on resume or unwind. May point back to the resumer.
55
56 // Currently tracked suspended native Await() calls.
57 // Invoked in FIFO order when this task completes.
60
61 // Where execution should continue when resuming.
62 FOp* ResumePC{nullptr};
64 VReturnSlot ResumeSlot; // May point into ResumeFrame or one of its ancestors.
65
66 // Where execution should continue when suspending.
67 FOp* YieldPC;
70
71 // Where execution should continue when complete.
74 TWriteBarrier<VTask> LastCancel;
75
76 // Links for the containing LastCancel or LastAwait list.
78 TWriteBarrier<VTask> NextTask;
79
80 COREUOBJECT_API static void BindStruct(FAllocationContext Context, VClass& TaskClass);
81 COREUOBJECT_API static void BindStructTrivial(FAllocationContext Context);
82
83 static VTask& New(FAllocationContext Context, FOp* YieldPC, VFrame* YieldFrame, VTask* YieldTask, VTask* Parent)
84 {
86 uint64 NumIndexedFields = TaskEmergentType.Shape->NumIndexedFields;
89 {
90 Debugger->AddTask(Context, Result);
91 }
92 return Result;
93 }
94
95 COREUOBJECT_API void AddToTaskGroup(FAllocationContext Context);
96 COREUOBJECT_API bool RemoveFromTaskGroup(FAllocationContext Context);
97
103 COREUOBJECT_API void Terminate(FAllocationContext Context);
104
107
110
111 bool Active() const { return Phase < EPhase::CancelStarted && !Result; }
112 bool Completed() const { return !!Result; }
113
114 COREUOBJECT_API static FOpResult ActiveImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
115 COREUOBJECT_API static FOpResult CompletedImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
116 COREUOBJECT_API static FOpResult CancelingImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
117 COREUOBJECT_API static FOpResult CanceledImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
118 COREUOBJECT_API static FOpResult UnsettledImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
119 COREUOBJECT_API static FOpResult SettledImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
120 COREUOBJECT_API static FOpResult UninterruptedImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
121 COREUOBJECT_API static FOpResult InterruptedImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
122
123 COREUOBJECT_API static FOpResult AwaitImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
124 COREUOBJECT_API static FOpResult CancelImpl(FRunningContext Context, VValue Scope, VNativeFunction::Args Arguments);
125
127
129 {
130 AutoRTFM::RecordOpenWrite(&Phase);
131 Phase = NewPhase;
132 }
133
135 {
136 AutoRTFM::RecordOpenWrite(&ResumePC);
138 }
139
141 {
142 AutoRTFM::RecordOpenWrite(&YieldPC);
144 }
145
146 bool RequestCancel(FRunningContext Context);
148
150 {
151 AutoRTFM::RecordOpenWrite(&bRunning);
152 bRunning = false;
153 }
154
156 {
157 AutoRTFM::RecordOpenWrite(&bRunning);
158 bRunning = true;
159 }
160
161 void Park(FAllocationContext Context, TWriteBarrier<VTask>& LastTask)
162 {
163 V_DIE_IF(PrevTask || NextTask);
164 if (LastTask)
165 {
166 PrevTask.SetTransactionally(Context, LastTask.Get());
167 LastTask->NextTask.SetTransactionally(Context, this);
168 }
169 LastTask.SetTransactionally(Context, this);
170 }
171
172 void Unpark(FAllocationContext Context, TWriteBarrier<VTask>& LastTask)
173 {
174 if (LastTask.Get() == this)
175 {
176 V_DIE_IF(NextTask);
177 LastTask.SetTransactionally(Context, PrevTask.Get());
178 }
179 if (PrevTask)
180 {
181 V_DIE_UNLESS(PrevTask->NextTask.Get() == this);
182 PrevTask->NextTask.SetTransactionally(Context, NextTask.Get());
183 }
184 if (NextTask)
185 {
186 V_DIE_UNLESS(NextTask->PrevTask.Get() == this);
187 NextTask->PrevTask.SetTransactionally(Context, PrevTask.Get());
188 }
189 PrevTask.ResetTransactionally(Context);
190 NextTask.ResetTransactionally(Context);
191 }
192
193 template <
194 typename FunctorType
196 !TIsTFunction<std::decay_t<FunctorType>>::Value && std::is_invocable_r_v<void, std::decay_t<FunctorType>, FAllocationContext, VTask*>)>
197 void Defer(FAllocationContext Context, FunctorType&& Func)
198 {
199 // This function expects to be run in the open
200 AutoRTFM::UnreachableIfClosed("#jira SOL-8415");
202
203 NativeDefer.SetTransactionally(Context, VTaskNativeHook::New(Context, Func));
204 }
205
206 template <
207 typename FunctorType
209 !TIsTFunction<std::decay_t<FunctorType>>::Value && std::is_invocable_r_v<void, std::decay_t<FunctorType>, FAllocationContext, VTask*>)>
210 void DeferOpen(FAllocationContext Context, FunctorType&& Func)
211 {
212 // This function expects to be run in the open
213 AutoRTFM::UnreachableIfClosed("#jira SOL-8415");
215
216 NativeDefer.SetTransactionally(Context, VTaskNativeHook::NewOpen(Context, Func));
217 }
218
219 void ClearDefer(FAllocationContext Context)
220 {
221 NativeDefer.ResetTransactionally(Context);
222 }
223
224 template <
225 typename FunctorType
227 !TIsTFunction<std::decay_t<FunctorType>>::Value && std::is_invocable_r_v<void, std::decay_t<FunctorType>, FAccessContext, VTask*>)>
228 void Await(FRunningContext Context, FunctorType&& Func)
229 {
230 Await(Context, VTaskNativeHook::New(Context, Func));
231 }
232
233 COREUOBJECT_API void ExecNativeDefer(FAllocationContext);
234 COREUOBJECT_API void ExecNativeAwaits(FAllocationContext);
235
236 struct FCallerSpec
237 {
238 FOp* PC;
239 VFrame* Frame;
241 };
242 COREUOBJECT_API static FCallerSpec MakeFrameForSpawn(FAllocationContext Context);
243
244 COREUOBJECT_API static void InitializeGlobals(FAllocationContext Context);
245
246 void AppendToStringImpl(FAllocationContext Context, FUtf8StringBuilderBase& Builder, EValueStringFormat Format, TSet<const void*>& VisitedObjects, uint32 RecursionDepth = 0);
247 static void SerializeLayout(FAllocationContext Context, VTask*& This, FStructuredArchiveVisitor& Visitor);
248 void SerializeImpl(FAllocationContext Context, FStructuredArchiveVisitor& Visitor);
249
250private:
252 {
253 TaskResult = FRegisterIndex::PARAMETER_START,
254 __MAX
255 };
256
260 , ResumeSlot(Context, nullptr)
264 {
265 }
266
267 COREUOBJECT_API void Await(FAllocationContext Context, VTaskNativeHook& Hook);
268
269 COREUOBJECT_API void TerminateRecursively(FAllocationContext Context);
270};
271
272// A counting semaphore with room for a single waiting task. Used for structured concurrency.
273struct VSemaphore : VCell
274{
277
279
280 static VSemaphore& New(FAllocationContext Context)
281 {
282 return *new (Context.AllocateFastCell(sizeof(VSemaphore))) VSemaphore(Context);
283 }
284
285 int32 IncrementCount(int32 Arg)
286 {
287 AutoRTFM::RecordOpenWrite(&Count);
288 Count += Arg;
289 return Count;
290 }
291
292 int32 DecrementCount(int32 Arg)
293 {
294 AutoRTFM::RecordOpenWrite(&Count);
295 Count -= Arg;
296 return Count;
297 }
298
299private:
300 VSemaphore(FAllocationContext Context)
302 {
303 }
304
305 int32 Count{0};
306};
307} // namespace Verse
308
309#endif
FPlatformTypes::int8 int8
An 8-bit signed integer.
Definition Platform.h:1121
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
T * New(FMemStackBase &Mem, int32 Count=1, int32 Align=DEFAULT_ALIGNMENT)
Definition MemStack.h:259
#define UE_REQUIRES(...)
Definition Requires.h:86
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition StringBuilder.h:79
void Suspend(bool bIsInterrupt=false)
Definition LaunchIOS.cpp:60
FORCEINLINE T * Get(const FObjectPtr &ObjectPtr)
Definition ObjectPtr.h:426
bool SerializeImpl(const UScriptStruct *InSourceEventType, const void *InSourceEventData, FLiveLinkSerializedFrameData &OutSerializedData)
Definition LiveLinkCompression.cpp:126
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732
Definition Archive.h:36
Definition FunctionFwd.h:32