2
0

allocators.odin 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #+private
  2. package os2
  3. import "base:runtime"
  4. @(require_results)
  5. file_allocator :: proc() -> runtime.Allocator {
  6. return heap_allocator()
  7. }
  8. @(private="file")
  9. MAX_TEMP_ARENA_COUNT :: 2
  10. @(private="file")
  11. MAX_TEMP_ARENA_COLLISIONS :: MAX_TEMP_ARENA_COUNT - 1
  12. @(private="file", thread_local)
  13. global_default_temp_allocator_arenas: [MAX_TEMP_ARENA_COUNT]runtime.Arena
  14. @(fini, private)
  15. temp_allocator_fini :: proc() {
  16. for &arena in global_default_temp_allocator_arenas {
  17. runtime.arena_destroy(&arena)
  18. }
  19. global_default_temp_allocator_arenas = {}
  20. }
  21. Temp_Allocator :: struct {
  22. using arena: ^runtime.Arena,
  23. using allocator: runtime.Allocator,
  24. tmp: runtime.Arena_Temp,
  25. loc: runtime.Source_Code_Location,
  26. }
  27. TEMP_ALLOCATOR_GUARD_END :: proc(temp: Temp_Allocator) {
  28. runtime.arena_temp_end(temp.tmp, temp.loc)
  29. }
  30. @(deferred_out=TEMP_ALLOCATOR_GUARD_END)
  31. TEMP_ALLOCATOR_GUARD :: #force_inline proc(collisions: []runtime.Allocator, loc := #caller_location) -> Temp_Allocator {
  32. assert(len(collisions) <= MAX_TEMP_ARENA_COLLISIONS, "Maximum collision count exceeded. MAX_TEMP_ARENA_COUNT must be increased!")
  33. good_arena: ^runtime.Arena
  34. for i in 0..<MAX_TEMP_ARENA_COUNT {
  35. good_arena = &global_default_temp_allocator_arenas[i]
  36. for c in collisions {
  37. if good_arena == c.data {
  38. good_arena = nil
  39. }
  40. }
  41. if good_arena != nil {
  42. break
  43. }
  44. }
  45. assert(good_arena != nil)
  46. if good_arena.backing_allocator.procedure == nil {
  47. good_arena.backing_allocator = heap_allocator()
  48. }
  49. tmp := runtime.arena_temp_begin(good_arena, loc)
  50. return { good_arena, runtime.arena_allocator(good_arena), tmp, loc }
  51. }
  52. temp_allocator_begin :: runtime.arena_temp_begin
  53. temp_allocator_end :: runtime.arena_temp_end
  54. @(deferred_out=_temp_allocator_end)
  55. temp_allocator_scope :: proc(tmp: Temp_Allocator) -> (runtime.Arena_Temp) {
  56. return temp_allocator_begin(tmp.arena)
  57. }
  58. @(private="file")
  59. _temp_allocator_end :: proc(tmp: runtime.Arena_Temp) {
  60. temp_allocator_end(tmp)
  61. }
  62. @(init, private)
  63. init_thread_local_cleaner :: proc() {
  64. runtime.add_thread_local_cleaner(temp_allocator_fini)
  65. }