Skip to content

Commit 99cc2e5

Browse files
authored
Merge pull request #33 from CapsCollective/feature/defer-utils
Implemented scoped defer utility
2 parents c60097c + 6a49564 commit 99cc2e5

File tree

3 files changed

+105
-2
lines changed

3 files changed

+105
-2
lines changed

engine/render/renderer/platform/vulkan/Texture2D.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#define STB_IMAGE_IMPLEMENTATION
1717
#include <stb_image.h>
18+
#include <utils/Defer.h>
1819
#include <utils/Logging.h>
1920

2021
namespace Siege::Vulkan
@@ -73,6 +74,7 @@ void Texture2D::LoadFromFile(const char* filePath)
7374
uint64_t imageSize = texWidth * texHeight * 4;
7475

7576
uint8_t* pixelPtr = new uint8_t[imageSize];
77+
defer([pixelPtr] { delete[] pixelPtr; });
7678

7779
// Set the image to 0 so that we get no garbage data in the pixel array
7880
memset(pixelPtr, 0, imageSize);
@@ -102,8 +104,6 @@ void Texture2D::LoadFromFile(const char* filePath)
102104
image.CopyBuffer(stagingBuffer.buffer);
103105

104106
Buffer::DestroyBuffer(stagingBuffer);
105-
106-
delete[] pixelPtr;
107107
}
108108

109109
void Texture2D::LoadTexture(const uint8_t* pixels, size_t size, uint32_t width, uint32_t height)

engine/utils/Defer.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// Copyright (c) 2023 Jonathan Moallem (@J-Mo63) & Aryeh Zinn (@Raelr)
3+
//
4+
// This code is released under an unmodified zlib license.
5+
// For conditions of distribution and use, please see:
6+
// https://opensource.org/licenses/Zlib
7+
//
8+
9+
#ifndef SIEGE_ENGINE_DEFER_H
10+
#define SIEGE_ENGINE_DEFER_H
11+
12+
#include <functional>
13+
14+
#include "Macros.h"
15+
16+
namespace Siege
17+
{
18+
19+
/**
20+
* A basic deferred call object implementation that executes its provided callable on scope exit.
21+
*/
22+
struct ScopedDefer
23+
{
24+
/**
25+
* Explicitly deleted zero-param constructor
26+
*/
27+
ScopedDefer() = delete;
28+
29+
/**
30+
* Constructor, specifying owned callable
31+
* @param callable - the void-returning, parameterless callable to execute
32+
*/
33+
explicit ScopedDefer(const std::function<void()>& callable) : callable(callable) {}
34+
35+
/**
36+
* Destructor, executing callable on scope exit
37+
*/
38+
~ScopedDefer()
39+
{
40+
callable();
41+
}
42+
43+
/**
44+
* Held void-retuning, parameterless callable
45+
*/
46+
std::function<void()> callable;
47+
};
48+
49+
#define _DEFER_VAR_NAME CONCAT_SYMBOL(_defer_, __COUNTER__)
50+
#define defer(callable) auto _DEFER_VAR_NAME = Siege::ScopedDefer(callable)
51+
52+
} // namespace Siege
53+
54+
#endif // SIEGE_ENGINE_DEFER_H

tests/utils/test_Defer.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// Copyright (c) 2022 Jonathan Moallem (@J-Mo63) & Aryeh Zinn (@Raelr)
3+
//
4+
// This code is released under an unmodified zlib license.
5+
// For conditions of distribution and use, please see:
6+
// https://opensource.org/licenses/Zlib
7+
//
8+
9+
#include <utest.h>
10+
#include <utils/Defer.h>
11+
12+
UTEST(test_Defer, BasicScopeDeferModify)
13+
{
14+
bool a = true;
15+
{
16+
ASSERT_TRUE(a);
17+
defer([&a] { a = false; });
18+
a = true;
19+
ASSERT_TRUE(a);
20+
}
21+
ASSERT_FALSE(a);
22+
}
23+
24+
UTEST(test_Defer, BasicScopeDeferDeletion)
25+
{
26+
auto* a = new bool;
27+
{
28+
ASSERT_TRUE(a);
29+
defer([&a] {
30+
delete a;
31+
a = nullptr;
32+
});
33+
ASSERT_TRUE(a);
34+
}
35+
ASSERT_FALSE(a);
36+
}
37+
38+
UTEST(test_Defer, LoopScopeDeferModify)
39+
{
40+
bool a = true;
41+
for (uint8_t i = 0; i < 3; ++i)
42+
{
43+
ASSERT_TRUE(a);
44+
defer([&a] { a = true; });
45+
a = false;
46+
ASSERT_FALSE(a);
47+
}
48+
ASSERT_TRUE(a);
49+
}

0 commit comments

Comments
 (0)