allocators.nim 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2017 Nim contributors
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. type
  10. AllocatorFlag* {.pure.} = enum ## flags describing the properties of the allocator
  11. ThreadLocal ## the allocator is thread local only.
  12. ZerosMem ## the allocator always zeros the memory on an allocation
  13. Allocator* = ptr AllocatorObj
  14. AllocatorObj* {.inheritable, compilerproc.} = object
  15. alloc*: proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall, raises: [], tags: [].}
  16. dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall, raises: [], tags: [].}
  17. realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall, raises: [], tags: [].}
  18. deallocAll*: proc (a: Allocator) {.nimcall, raises: [], tags: [].}
  19. flags*: set[AllocatorFlag]
  20. name*: cstring
  21. allocCount: int
  22. deallocCount: int
  23. var
  24. localAllocator {.threadvar.}: Allocator
  25. sharedAllocator: Allocator
  26. allocatorStorage {.threadvar.}: AllocatorObj
  27. when defined(useMalloc) and not defined(nimscript):
  28. import "system/ansi_c"
  29. import "system/memory"
  30. template `+!`(p: pointer, s: int): pointer =
  31. cast[pointer](cast[int](p) +% s)
  32. proc getLocalAllocator*(): Allocator =
  33. result = localAllocator
  34. if result == nil:
  35. result = addr allocatorStorage
  36. result.alloc = proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall, raises: [].} =
  37. when defined(useMalloc) and not defined(nimscript):
  38. result = c_malloc(size)
  39. # XXX do we need this?
  40. nimZeroMem(result, size)
  41. else:
  42. result = system.alloc0(size)
  43. inc a.allocCount
  44. result.dealloc = proc (a: Allocator; p: pointer; size: int) {.nimcall, raises: [].} =
  45. when defined(useMalloc) and not defined(nimscript):
  46. c_free(p)
  47. else:
  48. system.dealloc(p)
  49. inc a.deallocCount
  50. result.realloc = proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall, raises: [].} =
  51. when defined(useMalloc) and not defined(nimscript):
  52. result = c_realloc(p, newSize)
  53. else:
  54. result = system.realloc(p, newSize)
  55. nimZeroMem(result +! oldSize, newSize - oldSize)
  56. result.deallocAll = nil
  57. result.flags = {ThreadLocal, ZerosMem}
  58. result.name = "nim_local"
  59. localAllocator = result
  60. proc setLocalAllocator*(a: Allocator) =
  61. localAllocator = a
  62. proc getSharedAllocator*(): Allocator =
  63. result = sharedAllocator
  64. proc setSharedAllocator*(a: Allocator) =
  65. sharedAllocator = a
  66. proc allocCounters*(): (int, int) =
  67. let a = getLocalAllocator()
  68. result = (a.allocCount, a.deallocCount)