Skip to content

Commit cbaf38b

Browse files
authored
refactor: improve profiler consistency and error handling (#66)
1 parent f97249d commit cbaf38b

2 files changed

Lines changed: 28 additions & 9 deletions

File tree

include/DetourModKit/profiler.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@
4646

4747
// Scoped timing measurement. Name must be a string literal.
4848
#define DMK_PROFILE_SCOPE(name) \
49-
::DetourModKit::ScopedProfile DMK_CONCAT(dmk_scoped_profile_, __LINE__){name}
49+
::DetourModKit::ScopedProfile DMK_CONCAT(dmk_scoped_profile_, __LINE__) { name }
5050

5151
// Scoped timing using the enclosing function name.
5252
#define DMK_PROFILE_FUNCTION() \
53-
::DetourModKit::ScopedProfile DMK_CONCAT(dmk_scoped_profile_func_, __LINE__){__FUNCTION__}
53+
::DetourModKit::ScopedProfile DMK_CONCAT(dmk_scoped_profile_func_, __LINE__) { __func__ }
5454

5555
#else
5656

5757
#define DMK_PROFILE_SCOPE(name) ((void)0)
58-
#define DMK_PROFILE_FUNCTION() ((void)0)
58+
#define DMK_PROFILE_FUNCTION() ((void)0)
5959

6060
#endif // DMK_ENABLE_PROFILING
6161

@@ -171,10 +171,12 @@ namespace DetourModKit
171171
Profiler();
172172
~Profiler() = default;
173173

174+
// write_pos_ first to avoid 40 bytes of padding (alignas(64) requirement).
175+
// This placement ensures cache-line alignment for the lock-free ring buffer.
176+
alignas(64) std::atomic<size_t> write_pos_{0};
174177
std::unique_ptr<ProfileSample[]> buffer_;
175178
size_t capacity_;
176179
size_t mask_; // capacity_ - 1 for power-of-2 index wrapping
177-
alignas(64) std::atomic<size_t> write_pos_{0};
178180
int64_t qpc_frequency_{0};
179181
};
180182

src/profiler.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,32 @@ namespace DetourModKit
217217
const std::string json = export_chrome_json();
218218
const std::string path_str(path);
219219

220-
const auto closer = [](std::FILE *f) { std::fclose(f); };
221-
std::unique_ptr<std::FILE, decltype(closer)> fp(
222-
std::fopen(path_str.c_str(), "wb"), closer);
223-
if (!fp)
220+
const auto closer = [](std::FILE *f)
221+
{ std::fclose(f); };
222+
std::FILE *file_ptr = nullptr;
223+
224+
const errno_t err = fopen_s(&file_ptr, path_str.c_str(), "wb");
225+
if (err != 0 || file_ptr == nullptr)
224226
{
225227
return false;
226228
}
229+
230+
std::unique_ptr<std::FILE, decltype(closer)> fp(file_ptr, closer);
227231
const size_t written = std::fwrite(json.data(), 1, json.size(), fp.get());
228-
return written == json.size();
232+
if (written != json.size())
233+
{
234+
return false;
235+
}
236+
if (std::fflush(fp.get()) != 0)
237+
{
238+
return false;
239+
}
240+
// Release the pointer so unique_ptr does not double-close.
241+
if (std::fclose(fp.release()) != 0)
242+
{
243+
return false;
244+
}
245+
return true;
229246
}
230247

231248
size_t Profiler::total_samples_recorded() const noexcept

0 commit comments

Comments
 (0)