Skip to content

Commit

Permalink
Reverted coroutines explicit destroy from 3.3.6 as it was breaking th…
Browse files Browse the repository at this point in the history
…e heap allocator when running Garbage Collector.
  • Loading branch information
zompi2 committed Aug 1, 2024
1 parent 0fc7e68 commit b379aa6
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 34 deletions.
3 changes: 3 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
###### 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.
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.9",
"VersionName": "3.3.10",
"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: 3 additions & 0 deletions Source/EnhancedCodeFlow/EnhancedCodeFlow.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,8 @@ public EnhancedCodeFlow(ReadOnlyTargetRules Target) : base(Target)
{
PublicDefinitions.Add("ECF_INSIGHT_PROFILING=0");
}

// Enable when testing coroutines explicit destroy
PublicDefinitions.Add("ECF_USE_EXPLICIT_CORO_DESTROY=0");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,7 @@ class ENHANCEDCODEFLOW_API UECFRunAsyncAndWait: public UECFCoroutineActionBase

void Complete(bool bStopped) override
{
if (bHasValidCoroutineHandle)
{
CoroutineHandle.resume();
}
CoroutineHandle.resume();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ class ENHANCEDCODEFLOW_API UECFWaitSeconds : public UECFCoroutineActionBase

void Complete(bool bStopped) override
{
if (bHasValidCoroutineHandle)
{
CoroutineHandle.resume();
}
CoroutineHandle.resume();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ class ENHANCEDCODEFLOW_API UECFWaitTicks : public UECFCoroutineActionBase

void Complete(bool bStopped) override
{
if (bHasValidCoroutineHandle)
{
CoroutineHandle.resume();
}
CoroutineHandle.resume();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ class ENHANCEDCODEFLOW_API UECFWaitUntil : public UECFCoroutineActionBase

void Complete(bool bStopped) override
{
if (bHasValidCoroutineHandle)
{
CoroutineHandle.resume();
}
CoroutineHandle.resume();
}
};

Expand Down
10 changes: 8 additions & 2 deletions Source/EnhancedCodeFlow/Public/Coroutines/ECFCoroutine.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ 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
#if ECF_USE_EXPLICIT_CORO_DESTROY
std::suspend_always final_suspend() noexcept { return {}; }
#else
std::suspend_never final_suspend() noexcept { return {}; }
#endif
void return_void() {}
void unhandled_exception() {}

int32 HandleCounter = 0;
bool bDestroyed = false;
};

#else
Expand All @@ -38,7 +45,6 @@ using FECFCoroutine = void;
struct FECFCoroutineHandle
{
void resume() {};
void destroy() {};
};

#define co_await static_assert(false, "Trying to use co_await without coroutine support!")
Expand Down
42 changes: 27 additions & 15 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,27 +16,32 @@ class ENHANCEDCODEFLOW_API UECFCoroutineActionBase : public UECFActionBase

friend class UECFSubsystem;

public:
protected:

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

// Ensure the coroutine handle is properly destroyed.
// Remember, that the Promise has final_suspend set to always.
#ifdef __cpp_impl_coroutine
#if ECF_USE_EXPLICIT_CORO_DESTROY
bool bHasValidCoroHandle = false;
void BeginDestroy() override
{
if (bHasValidCoroutineHandle)
if (bHasValidCoroHandle)
{
CoroutineHandle.destroy();
bHasValidCoroutineHandle = false;
if (CoroutineHandle.promise().bDestroyed == false)
{
CoroutineHandle.promise().HandleCounter--;
if (CoroutineHandle.promise().HandleCounter <= 0)
{
CoroutineHandle.promise().bDestroyed = true;
CoroutineHandle.destroy();
}
}
}
Super::BeginDestroy();
}

protected:

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

// Flag indicating if the coroutine handle is valid and safe to be destroyed.
bool bHasValidCoroutineHandle = false;
#endif
#endif

private:

Expand All @@ -44,7 +50,13 @@ class ENHANCEDCODEFLOW_API UECFCoroutineActionBase : public UECFActionBase
{
UECFActionBase::SetAction(InOwner, InHandleId, {}, InSettings);
CoroutineHandle = InCoroutineHandle;
bHasValidCoroutineHandle = true;

#ifdef __cpp_impl_coroutine
#if ECF_USE_EXPLICIT_CORO_DESTROY
CoroutineHandle.promise().HandleCounter++;
bHasValidCoroHandle = true;
#endif
#endif
}
};

Expand Down

0 comments on commit b379aa6

Please sign in to comment.