v / vlib / v2 / profiler / context.v
76 lines · 62 sloc · 2.14 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1// Copyright (c) 2026 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module profiler
5
6import context
7
8// Allocator interface - can be swapped at runtime
9// Similar to Jai's context.allocator design
10pub struct Allocator {
11pub:
12 alloc_fn fn (size int, ctx voidptr) voidptr = default_alloc
13 free_fn fn (ptr voidptr, ctx voidptr) = default_free
14 realloc_fn fn (ptr voidptr, new_size int, ctx voidptr) voidptr = default_realloc
15 ctx voidptr // User data for allocator implementation
16}
17
18// Thread-local context (implicit parameter)
19// This allows all allocations in a scope to be tracked without explicit annotations
20
21@[thread_local]
22__global context = Context{}
23
24pub struct Context {
25pub mut:
26 allocator Allocator = default_allocator
27}
28
29// Default allocator - just wraps malloc/free/realloc
30pub const default_allocator = Allocator{
31 alloc_fn: default_alloc
32 free_fn: default_free
33 realloc_fn: default_realloc
34 ctx: unsafe { nil }
35}
36
37fn default_alloc(size int, ctx voidptr) voidptr {
38 return unsafe { C.malloc(size) }
39}
40
41fn default_free(ptr voidptr, ctx voidptr) {
42 unsafe { C.free(ptr) }
43}
44
45fn default_realloc(ptr voidptr, new_size int, ctx voidptr) voidptr {
46 return unsafe { C.realloc(ptr, new_size) }
47}
48
49// User code calls these - they use context.allocator implicitly
50// This provides the Jai-like implicit allocation tracking
51pub fn alloc(size int) voidptr {
52 return context.allocator.alloc_fn(size, context.allocator.ctx)
53}
54
55pub fn free(ptr voidptr) {
56 context.allocator.free_fn(ptr, context.allocator.ctx)
57}
58
59pub fn realloc(ptr voidptr, new_size int) voidptr {
60 return context.allocator.realloc_fn(ptr, new_size, context.allocator.ctx)
61}
62
63// Scoped allocator helper - saves and restores the allocator
64// Usage:
65// old := profiler.push_allocator(my_allocator)
66// defer { profiler.pop_allocator(old) }
67// // ... all allocations here use my_allocator
68pub fn push_allocator(a Allocator) Allocator {
69 old := context.allocator
70 context.allocator = a
71 return old
72}
73
74pub fn pop_allocator(old Allocator) {
75 context.allocator = old
76}
77