diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nimbase.h | 7 | ||||
-rw-r--r-- | lib/system.nim | 62 | ||||
-rw-r--r-- | lib/wrappers/zmq.nim | 7 |
3 files changed, 63 insertions, 13 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index 19d161adf..1100e084b 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -285,8 +285,8 @@ static N_INLINE(NI32, float32ToInt32)(float x) { typedef struct TStringDesc* string; -/* declared size of a sequence: */ -#if defined(__GNUC__) +/* declared size of a sequence/variable length array: */ +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) # define SEQ_DECL_SIZE /* empty is correct! */ #else # define SEQ_DECL_SIZE 1000000 @@ -373,5 +373,8 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } # define GC_GUARD #endif +/* Test to see if nimrod and the C compiler agrees on the size of a pointer. + On disagreement, your C compiler will say something like: + "error: 'assert_numbits' declared as an array with a negative size" */ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; #endif diff --git a/lib/system.nim b/lib/system.nim index 869658727..171c7b6b8 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -185,6 +185,8 @@ proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} = when not defined(niminheritable): {.pragma: inheritable.} +when not defined(nimunion): + {.pragma: unchecked.} const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \ ## "fake variables" like 'var EBADF {.importc.}: cint'. @@ -194,9 +196,10 @@ when not defined(JS): TGenericSeq {.compilerproc, pure, inheritable.} = object len, reserved: int PGenericSeq {.exportc.} = ptr TGenericSeq + UncheckedCharArray {.unchecked.} = array[0..100_000_000, char] # len and space without counting the terminating zero: NimStringDesc {.compilerproc, final.} = object of TGenericSeq - data: array[0..100_000_000, char] + data: UncheckedCharArray NimString = ptr NimStringDesc when not defined(JS) and not defined(NimrodVM): @@ -1161,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 @@ -1168,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 @@ -1184,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/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim index 4e658028e..9826ab813 100644 --- a/lib/wrappers/zmq.nim +++ b/lib/wrappers/zmq.nim @@ -299,12 +299,12 @@ proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER, else: if connect(result.s, address) != 0'i32: zmqError() -proc close*(c: var TConnection) = +proc close*(c: TConnection) = ## closes the connection. if close(c.s) != 0'i32: zmqError() if term(c.c) != 0'i32: zmqError() -proc send*(c: var TConnection, msg: string) = +proc send*(c: TConnection, msg: string) = ## sends a message over the connection. var m: TMsg if msg_init(m, msg.len) != 0'i32: zmqError() @@ -312,7 +312,7 @@ proc send*(c: var TConnection, msg: string) = if send(c.s, m, 0'i32) != 0'i32: zmqError() discard msg_close(m) -proc receive*(c: var TConnection): string = +proc receive*(c: TConnection): string = ## receives a message from a connection. var m: TMsg if msg_init(m) != 0'i32: zmqError() @@ -320,4 +320,3 @@ proc receive*(c: var TConnection): string = result = newString(msg_size(m)) copyMem(addr(result[0]), msg_data(m), result.len) discard msg_close(m) - |