Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit ab18e28

Browse files
committed
Library: Refactor (see desc)
- Hold API pointers across DLL boundaries - Ensure SPALL_BUFFER_PROFILING works with SPALL_JSON - Ensure SPALL_BUFFER_PROFILING works with SPALL_DEBUG - Ensure SPALL_JSON works with SPALL_DEBUG
1 parent cf2a9f7 commit ab18e28

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

spall.h

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,9 @@ typedef struct SpallEndEvent {
9393

9494
typedef struct SpallProfile {
9595
double timestamp_unit;
96-
bool (*write)(struct SpallProfile *self, void *data, size_t length);
96+
bool (*write)(struct SpallProfile *self, const void *data, size_t length);
9797
bool (*flush)(struct SpallProfile *self);
98+
void (*close)(struct SpallProfile *self);
9899
union {
99100
FILE *file;
100101
void *userdata;
@@ -159,16 +160,18 @@ extern "C" {
159160
#endif
160161

161162
#ifdef SPALL_BUFFER_PROFILING
163+
static void Spall__BufferProfile(SpallProfile *ctx, SpallBuffer *wb, double spall_time_begin, double spall_time_end, const char *name, int name_len) {
164+
// precon: ctx
165+
// precon: ctx->write
166+
char temp_buffer_data[2048];
167+
SpallBuffer temp_buffer = { temp_buffer_data, sizeof(temp_buffer_data) };
168+
if (!SpallTraceBeginLenTidPid(ctx, &temp_buffer, name, sizeof(name) - 1, (uint32_t)(uintptr_t)wb->data, 4222222222, spall_time_begin)) return;
169+
if (!SpallTraceEndTidPid(ctx, &temp_buffer, (uint32_t)(uintptr_t)wb->data, 4222222222, spall_time_end)) return;
170+
ctx->write(ctx, temp_buffer_data, temp_buffer.head);
171+
}
162172
#define SPALL_BUFFER_PROFILE_BEGIN() double spall_time_begin = (SPALL_BUFFER_PROFILING_GET_TIME())
163173
// Don't call this with anything other than a string literal
164-
#define SPALL_BUFFER_PROFILE_END(name) do { \
165-
double spall_time_end = (SPALL_BUFFER_PROFILING_GET_TIME()); \
166-
char temp_buffer_data[sizeof(SpallBeginEvent) + sizeof("" name "") - 1 + sizeof(SpallEndEvent)]; \
167-
SpallBuffer temp_buffer = {temp_buffer_data, sizeof(temp_buffer_data)}; \
168-
if (!SpallTraceBeginLenTidPid(ctx, &temp_buffer, name, sizeof(name) - 1, (uint32_t)(uintptr_t)wb->data, 4222222222, spall_time_begin)) return false; \
169-
if (!SpallTraceEndTidPid(ctx, &temp_buffer, (uint32_t)(uintptr_t)wb->data, 4222222222, spall_time_end)) return false; \
170-
if (!Spall__FileWrite(ctx, temp_buffer_data, sizeof(temp_buffer_data))) return false; \
171-
} while (0)
174+
#define SPALL_BUFFER_PROFILE_END(name) Spall__BufferProfile(ctx, wb, spall_time_begin, (SPALL_BUFFER_PROFILING_GET_TIME()), "" name "", sizeof("" name "") - 1)
172175
#else
173176
#define SPALL_BUFFER_PROFILE_BEGIN()
174177
#define SPALL_BUFFER_PROFILE_END(name)
@@ -178,7 +181,7 @@ extern char SpallSingleThreadedBufferData[];
178181
char SpallSingleThreadedBufferData[1 << 16];
179182
SpallBuffer SpallSingleThreadedBuffer = {SpallSingleThreadedBufferData, sizeof(SpallSingleThreadedBufferData)};
180183

181-
static bool Spall__FileWrite(SpallProfile *ctx, void *p, size_t n) {
184+
static bool Spall__FileWrite(SpallProfile *ctx, const void *p, size_t n) {
182185
if (!ctx->file) return false;
183186
#ifdef SPALL_DEBUG
184187
if (feof(ctx->file)) return false;
@@ -193,11 +196,28 @@ static bool Spall__FileFlush(SpallProfile *ctx) {
193196
if (fflush(ctx->file)) return false;
194197
return true;
195198
}
199+
static void Spall__FileClose(SpallProfile *ctx) {
200+
if (!ctx->file) return;
201+
202+
#ifdef SPALL_JSON
203+
#ifdef SPALL_DEBUG
204+
if (!feof(ctx->file) && !ferror(ctx->file))
205+
#endif
206+
{
207+
fseek(ctx->file, -2, SEEK_CUR); // seek back to overwrite trailing comma
208+
fwrite("\n]}\n", sizeof("\n]}\n") - 1, 1, ctx->file);
209+
}
210+
#endif
211+
fflush(ctx->file);
212+
fclose(ctx->file);
213+
ctx->file = NULL;
214+
}
196215

197216
static bool Spall__BufferFlush(SpallProfile *ctx, SpallBuffer *wb) {
198217
// precon: wb
199218
// precon: wb->data
200219
// precon: wb->head <= wb->length
220+
// precon: !ctx || ctx->write
201221
#ifdef SPALL_DEBUG
202222
if (wb->ctx != ctx) return false; // Buffer must be bound to this context (or to NULL)
203223
#endif
@@ -213,8 +233,11 @@ static bool Spall__BufferFlush(SpallProfile *ctx, SpallBuffer *wb) {
213233

214234
static bool Spall__BufferWrite(SpallProfile *ctx, SpallBuffer *wb, void *p, size_t n) {
215235
// precon: !wb || wb->head < wb->length
216-
// precon: ctx->file
236+
// precon: !ctx || ctx->write
217237
if (!wb) return ctx->write(ctx, p, n);
238+
#ifdef SPALL_DEBUG
239+
if (wb->ctx != ctx) return false; // Buffer must be bound to this context (or to NULL)
240+
#endif
218241
if (wb->head + n > wb->length && !Spall__BufferFlush(ctx, wb)) return false;
219242
if (n > wb->length) {
220243
SPALL_BUFFER_PROFILE_BEGIN();
@@ -263,6 +286,7 @@ static SpallProfile Spall__Init(const char *filename, double timestamp_unit) {
263286
ctx.file = fopen(filename, "wb"); // TODO: handle utf8 and long paths on windows
264287
ctx.write = Spall__FileWrite;
265288
ctx.flush = Spall__FileFlush;
289+
ctx.close = Spall__FileClose;
266290
if (!ctx.file) { SpallQuit(&ctx); return ctx; }
267291
ctx.timestamp_unit = timestamp_unit;
268292

@@ -284,17 +308,7 @@ SpallProfile SpallInit (const char *filename, double timestamp_unit) { return
284308

285309
void SpallQuit(SpallProfile *ctx) {
286310
if (!ctx) return;
287-
if (ctx->file) {
288-
#ifdef SPALL_JSON
289-
fseek(ctx->file, -2, SEEK_CUR); // seek back to overwrite trailing comma
290-
fprintf(ctx->file, "\n]}\n");
291-
fflush(ctx->file);
292-
fclose(ctx->file);
293-
#else
294-
fflush(ctx->file);
295-
fclose(ctx->file);
296-
#endif
297-
}
311+
if (ctx->close) ctx->close(ctx);
298312

299313
memset(ctx, 0, sizeof(*ctx));
300314
}

0 commit comments

Comments
 (0)