Squid::Tasks 1.0.0
C++14 coroutine-based task library for games
Function Guard

Scope guard that calls a function as it leaves scope. More...

Classes

class  FunctionGuard< tFn >
 

Functions

template<typename tFn >
FunctionGuard< tFn > MakeFnGuard (tFn in_fn)
 Create a function guard (directly stores the concretely-typed functor in the FunctionGuard)
 
FunctionGuard MakeGenericFnGuard (std::function< void()> in_fn)
 Create a generic function guard (preferable when re-assigning new functor values to the same variable)
 

Detailed Description

Scope guard that calls a function as it leaves scope.

A FunctionGuard is an scope guard object that stores a functor that will be called from its destructor. By convention, scope guards are move-only objects that are intended for allocation on the stack, to ensure that certain operations are performed exactly once (when their scope collapses).

Because tasks can be canceled while suspended (and thus do not reach the end of the function), any cleanup code at the end of a task isn't guaranteed to execute. Because FunctionGuard is an RAII object, it gives programmers an opportunity to schedule guaranteed cleanup code, no matter how a task terminates.

Consider the following example of a task that manages a character's "charge attack" in a combat-oriented game:

class Character : public Actor
{
public:
Task<> ChargeAttackState()
{
bool bIsFullyCharged = false;
if(Input->IsAttackButtonPressed())
{
StartCharging(); // Start playing charge effects
auto stopChargingGuard = MakeFnGuard([&]{
StopCharging(); // Stop playing charge effects
});
// Wait for N seconds (canceling if button is no longer held)
bIsFullyCharged = co_await WaitSeconds(chargeTime).CancelIf([&] {
return !Input->IsAttackButtonPressed();
});
} // <-- This is when StopCharging() will be called
FireShot(bIsFullyCharged);
}
};
Definition: Task.h:204
Task< tTaskTime > WaitSeconds(tTaskTime in_seconds, tTimeFn in_timeFn)
Awaiter function that waits N seconds in a given time-stream.
Definition: Task.h:850
FunctionGuard< tFn > MakeFnGuard(tFn in_fn)
Create a function guard (directly stores the concretely-typed functor in the FunctionGuard)
Definition: FunctionGuard.h:115

In the above example, we can guarantee that StopCharging will logically be called exactly once for every call to StartCharging(), even the ChargeAttackState() task is killed or canceled. Furthermore, we know that StopCharging() will always be called prior to the call to FireShot().

In practice, it is often desirable to create more domain-specific scope guards for specific use cases, but FunctionGuard provides a simple general-purpose tool for writing robust, water-tight coroutine logic without the overhead of creating bespoke support classes.