diff options
-rw-r--r-- | lib/system.nim | 57 | ||||
-rw-r--r-- | tests/system/alloc.nim | 45 |
2 files changed, 96 insertions, 6 deletions
diff --git a/lib/system.nim b/lib/system.nim index 5e27bd83a..171c7b6b8 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1164,6 +1164,14 @@ when not defined(nimrodVM): ## from it before writing to it is undefined behaviour! ## The allocated memory belongs to its allocating thread! ## Use `allocShared` to allocate from a shared heap. + proc alloc*(T: typedesc, size = 1): ptr T {.inline.} = + ## allocates a new memory block with at least ``T.sizeof * size`` + ## bytes. The block has to be freed with ``realloc(block, 0)`` or + ## ``dealloc(block)``. The block is not initialized, so reading + ## from it before writing to it is undefined behaviour! + ## The allocated memory belongs to its allocating thread! + ## Use `allocShared` to allocate from a shared heap. + cast[ptr T](alloc(T.sizeof * size)) proc alloc0*(size: int): pointer {.noconv, rtl, tags: [].} ## allocates a new memory block with at least ``size`` bytes. The ## block has to be freed with ``realloc(block, 0)`` or @@ -1171,14 +1179,31 @@ when not defined(nimrodVM): ## containing zero, so it is somewhat safer than ``alloc``. ## The allocated memory belongs to its allocating thread! ## Use `allocShared0` to allocate from a shared heap. - proc realloc*(p: pointer, newsize: int): pointer {.noconv, rtl, tags: [].} + proc alloc0*(T: typedesc, size = 1): ptr T {.inline.} = + ## allocates a new memory block with at least ``T.sizeof * size`` + ## bytes. The block has to be freed with ``realloc(block, 0)`` or + ## ``dealloc(block)``. The block is initialized with all bytes + ## containing zero, so it is somewhat safer than ``alloc``. + ## The allocated memory belongs to its allocating thread! + ## Use `allocShared0` to allocate from a shared heap. + cast[ptr T](alloc0(T.sizeof * size)) + proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [].} ## grows or shrinks a given memory block. If p is **nil** then a new ## memory block is returned. In either way the block has at least - ## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil** + ## ``newSize`` bytes. If ``newSize == 0`` and p is not **nil** ## ``realloc`` calls ``dealloc(p)``. In other cases the block has to ## be freed with ``dealloc``. ## The allocated memory belongs to its allocating thread! ## Use `reallocShared` to reallocate from a shared heap. + proc reallocType*[T](p: ptr T, newSize: int): ptr T {.inline.} = + ## grows or shrinks a given memory block. If p is **nil** then a new + ## memory block is returned. In either way the block has at least + ## ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is not + ## **nil** ``realloc`` calls ``dealloc(p)``. In other cases the block + ## has to be freed with ``dealloc``. The allocated memory belongs to + ## its allocating thread! + ## Use `reallocShared` to reallocate from a shared heap. + cast[ptr T](realloc(p, T.sizeof * newSize)) proc dealloc*(p: pointer) {.noconv, rtl, tags: [].} ## frees the memory allocated with ``alloc``, ``alloc0`` or ## ``realloc``. This procedure is dangerous! If one forgets to @@ -1187,25 +1212,45 @@ when not defined(nimrodVM): ## or other memory may be corrupted. ## The freed memory must belong to its allocating thread! ## Use `deallocShared` to deallocate from a shared heap. - proc allocShared*(size: int): pointer {.noconv, rtl.} ## allocates a new memory block on the shared heap with at ## least ``size`` bytes. The block has to be freed with ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block ## is not initialized, so reading from it before writing to it is ## undefined behaviour! + proc allocShared*(T: typedesc, size: int): ptr T {.inline.} = + ## allocates a new memory block on the shared heap with at + ## least ``T.sizeof * size`` bytes. The block has to be freed with + ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block + ## is not initialized, so reading from it before writing to it is + ## undefined behaviour! + cast[ptr T](allocShared(T.sizeof * size)) proc allocShared0*(size: int): pointer {.noconv, rtl.} ## allocates a new memory block on the shared heap with at ## least ``size`` bytes. The block has to be freed with ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. ## The block is initialized with all bytes ## containing zero, so it is somewhat safer than ``allocShared``. - proc reallocShared*(p: pointer, newsize: int): pointer {.noconv, rtl.} + proc allocShared0*(T: typedesc, size: int): ptr T {.inline.} = + ## allocates a new memory block on the shared heap with at + ## least ``T.sizeof * size`` bytes. The block has to be freed with + ## ``reallocShared(block, 0)`` or ``deallocShared(block)``. + ## The block is initialized with all bytes + ## containing zero, so it is somewhat safer than ``allocShared``. + cast[ptr T](allocShared(T.sizeof * size)) + proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl.} ## grows or shrinks a given memory block on the heap. If p is **nil** - ## then a new memory block is returned. In either way the block has at least - ## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil** + ## then a new memory block is returned. In either way the block has at + ## least ``newSize`` bytes. If ``newSize == 0`` and p is not **nil** ## ``reallocShared`` calls ``deallocShared(p)``. In other cases the ## block has to be freed with ``deallocShared``. + proc reallocSharedType*[T](p: ptr T, newSize: int): ptr T {.inline.} = + ## grows or shrinks a given memory block on the heap. If p is **nil** + ## then a new memory block is returned. In either way the block has at + ## least ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is + ## not **nil** ``reallocShared`` calls ``deallocShared(p)``. In other + ## cases the block has to be freed with ``deallocShared``. + cast[ptr T](reallocShared(p, T.sizeof * newSize)) proc deallocShared*(p: pointer) {.noconv, rtl.} ## frees the memory allocated with ``allocShared``, ``allocShared0`` or ## ``reallocShared``. This procedure is dangerous! If one forgets to diff --git a/tests/system/alloc.nim b/tests/system/alloc.nim new file mode 100644 index 000000000..665b448ac --- /dev/null +++ b/tests/system/alloc.nim @@ -0,0 +1,45 @@ +var x: ptr int + +x = cast[ptr int](alloc(7)) +assert x != nil + +x = alloc(int, 3) +assert x != nil +x.dealloc() + +x = alloc0(int, 4) +assert cast[ptr array[4, int]](x)[0] == 0 +assert cast[ptr array[4, int]](x)[1] == 0 +assert cast[ptr array[4, int]](x)[2] == 0 +assert cast[ptr array[4, int]](x)[3] == 0 + +x = cast[ptr int](x.realloc(2)) +assert x != nil + +x = x.reallocType(4) +assert x != nil +x.dealloc() + +x = cast[ptr int](allocShared(100)) +assert x != nil +deallocShared(x) + +x = allocShared(int, 3) +assert x != nil +x.deallocShared() + +x = allocShared0(int, 3) +assert x != nil +assert cast[ptr array[3, int]](x)[0] == 0 +assert cast[ptr array[3, int]](x)[1] == 0 +assert cast[ptr array[3, int]](x)[2] == 0 + +x = cast[ptr int](reallocShared(x, 2)) +assert x != nil + +x = reallocType(x, 12) +assert x != nil + +x = reallocSharedType(x, 1) +assert x != nil +x.deallocShared() |