Skip to content

Commit

Permalink
Merge branch 'main' into more-timeline-types
Browse files Browse the repository at this point in the history
  • Loading branch information
zompi2 committed Aug 5, 2024
2 parents fb667af + af855ef commit cd8d41b
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 20 deletions.
10 changes: 10 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
###### 3.3.11
* Proper coroutine handle destruction for dangling handles.

###### 3.3.10
* Reverted coroutines explicit destroy from 3.3.6 as it was breaking the heap allocator when running Garbage Collector.

###### 3.3.9
* Fixed ECFHandle badly passed to the coroutine action.
* Ensuring coroutine handles are valid before resuming them.

###### 3.3.8
* Fixed coroutines compilation for the environment without coroutines support (which has been broken in 3.3.6).

Expand Down
2 changes: 1 addition & 1 deletion EnhancedCodeFlow.uplugin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "3.3.8",
"VersionName": "3.3.11",
"FriendlyName": "Enhanced Code Flow",
"Description": "This code plugin provides functions that drastically improve the quality of life during the implementation of game flow in C++.",
"Category": "Programming",
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The plugin is finally available on the Unreal Engine Marketplace! It is free, of
If you don't want to build this plugin by yourself, you can **[download it from here](https://www.unrealengine.com/marketplace/en-US/product/enhanced-code-flow)**.
Unreal Engine Marketplace allow to publish the code plugins for new versions of the Unreal Engine only, so currently only 5.4, 5.3 and 5.2 are available.
If you are using 4.27 you can download the precompiled package **[from here](https://github.com/zompi2/UE4EnhancedCodeFlow/raw/build-4.27/EnhancedCodeFlow-4.27-Compiled.zip)**.
The plugin's version that's on the Marketplace is **3.3.4**.
The plugin's version that's on the Marketplace is **3.3.10**.

[Back to top](#table-of-content)

Expand Down Expand Up @@ -535,6 +535,7 @@ There is additional BP node which will validate an `InstanceId` if it is not val
# Coroutines (experimental)

> Coroutines are treated as an **experimental** feature. You can use them at your own risk!
> They are experimental, because c++ coroutines are relatively new features and I'm still learning how to implement them correctly. It is highly propable there will be stability or performance issues.
[Coroutines](https://en.cppreference.com/w/cpp/language/coroutines) are functions that can suspend their execution and be resumed later. They require C++20 which is supported in Unreal Engine from verion 5.3. To make sure that your project supports C++20 add the following line to your project's `Build.cs`:

Expand Down
17 changes: 13 additions & 4 deletions Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ struct FECFCoroutinePromise
{
FECFCoroutine get_return_object() { return { FECFCoroutine::from_promise(*this) }; }
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; } // The handle will always be destroyed manually
void return_void() {}
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() { bHasFinished = true; }
void unhandled_exception() {}
bool bHasFinished = false;
};

#else
Expand All @@ -35,10 +36,18 @@ struct FECFCoroutinePromise

using FECFCoroutine = void;

struct FECFCoroutinePromise
{
bool bHasFinished = false;
};

struct FECFCoroutineHandle
{
void resume() {};
void destroy() {};
void resume() {}
void destroy() {}

FECFCoroutinePromise CoroPromise;
FECFCoroutinePromise& promise() { return CoroPromise; }
};

#define co_await static_assert(false, "Trying to use co_await without coroutine support!")
Expand Down
28 changes: 14 additions & 14 deletions Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutineActionBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "ECFActionBase.h"
#include "ECFCoroutine.h"
#include "ECFSubsystem.h"
#include "ECFCoroutineActionBase.generated.h"

ECF_PRAGMA_DISABLE_OPTIMIZATION
Expand All @@ -15,35 +16,34 @@ class ENHANCEDCODEFLOW_API UECFCoroutineActionBase : public UECFActionBase

friend class UECFSubsystem;

public:
protected:

// Coroutine handle used to control the coroutine inside the Action.
FECFCoroutineHandle CoroutineHandle;

// Flag indicating if the coroutine handle has been set.
bool bHasCoroutineHandle = false;

// Ensure the coroutine handle is properly destroyed.
// Remember, that the Promise has final_suspend set to always.
void BeginDestroy() override
{
if (bHasValidCoroutineHandle)
// Handling a case when the owner has beed destroyed before the coroutine has been fully finished.
// In such case the handle must be explicitly destroyed.
if (bHasCoroutineHandle && (HasValidOwner() == false) && (CoroutineHandle.promise().bHasFinished == false))
{
CoroutineHandle.promise().bHasFinished = true;
CoroutineHandle.destroy();
}
Super::BeginDestroy();
}

protected:

// Coroutine handle used to control the coroutine inside the Action.
FECFCoroutineHandle CoroutineHandle;

//
bool bHasValidCoroutineHandle = false;

private:

// Setting up action. The same as in ActionBase, but it additionally sets the coroutine handle.
void SetCoroutineAction(const UObject* InOwner, FECFCoroutineHandle InCoroutineHandle, const FECFHandle& InHandleId, const FECFActionSettings& InSettings)
{
UECFActionBase::SetAction(InOwner, HandleId, {}, InSettings);
UECFActionBase::SetAction(InOwner, InHandleId, {}, InSettings);
CoroutineHandle = InCoroutineHandle;
bHasValidCoroutineHandle = true;
bHasCoroutineHandle = true;
}
};

Expand Down

0 comments on commit cd8d41b

Please sign in to comment.