# Allocator tooling The CURALLOC system described at [usage/mem] doesn't need any kind of tooling to work. You create a struct, set CURALLOC to it, then you're done. However, to make allocators convenient to use, a small layer of words can be useful. This unit is that layer. All allocators such as [mem/scratch] and [mem/arena] use this layer. This layer also serves to set some patterns that are used throughout Dusk. For example, that activator binds end with "[", run1 binds end with "1" and run1 fetchers end with "1@". Nothing forces us to these patterns, but to adhere to them helps code clarity. ## Allocator creation and activation We can say that everything in mem/alloc revolves around "newallocator", "alloc[" and "]alloc". "newallocator" is a simple wrapper word around the HERE/HEREMAX/NEWHERE triple which write that structure down in a CURALLOC-compatible way. "alloc[ ( alloc -- )" pushes current CURALLOC to a static stack [mem/stack] and then sets it to specified "alloc". It also calls "alignhere" afterwards. That is an important pattern in Dusk: whenever allocators are activated, they're automatically aligned. This can simplify their usage a lot. "alloc[" is seldom used directly because most allocator usages is done through bindings (see below). "]alloc ( -- )" pops the previously selected allocator from its static stack and set CURALLOC to it. Unless you create a new allocator type, you will not need to use "newallocator". ## Bindings Allocators bindings is how you'll interact with allocators. There are several types of bindings. All those bindings work in both interpret and compile mode. ### bindalloc[ "bindalloc[" binds an allocator to the "alloc[" word. Example: $100 newscratchpad bindalloc[ mypad[ mypad[ 4 allot@ ]alloc \ PS contains 4b alloc from pad, back on system memory ### bindrun1 "bindrun1" binds a single word runner that automatically calls "]alloc" afterwards: $100 newscratchpad bindrun1 mypad1 4 mypad1 allot@ \ same effect as example above ### bindrun1@ "bindrun1@" is the same as "bindrun1", except that it uses the PREVRESERVE [doc/dict] variable to yield the address of the allocated memory: $100 newscratchpad bindrun1@ mypad1@ 4 mypad1@ allot \ same effect as example above This last binding allows us to avoid creating tons of speciality allocation words. Sure, we have allot@ as a "yielding" alternative to "allot", but do we have a "s,@" or a "cmoveallot@"? No we don't. In these cases, "bindrun1@" is really useful. The word that is thus yielded is either where "here" was right before the call **OR**, if "newhere" was called during the execution of that word, the address that "newhere" yielded. This binding thus only works for "proper" allocator words, that is, words that properly reserve their memory before writing to it. ### bindrun1r "bindrun1r" is like "bindrun1" except that it expects a word that has a ( ... -- ... a ) signature with "a" being the address allocated within the word. We expect that allocation to be a "proper" single allocation, that is, properly reserved first. In fact, the whole point of this bind is to make sure that we do. To do so, we check that the yielded "a" is the exact same as the one that "bindrun1@" would yield. If it's not, abort with contiguity error because in all likeliness, this discrepancy means that the address thus yielded contains non- contiguous data. ## API newallocator ( newhere a u -- alloc ) Create a new HERE/HEREMAX/NEWHERE allocator with specified range. "newhere" must be a pointer to a word with a "( -- a u )" signature. This allocator is suitable make CURALLOC point to it. alloc ( n alloc -- a ) Exactly like "allot@", but in the specified allocator. alloc[ ( alloc -- ) Push current CURALLOC to static stack, then set CURALLOC to "alloc" and then call "alignhere". Aborts on static stack overflow. ]alloc ( -- ) Pop from static stack and set CURALLOC to this. Aborts on static stack underflow. ]sysmem ( -- ) Empties static stack and set CURALLOC to SYSALLOC. bindalloc[ ( alloc "name" -- ) *A* bindrun1 ( alloc "name" -- ) *A* bindrun1@ ( alloc "name" -- ) *A* bindrun1r ( alloc "name" -- ) *A* See description above. All bindings preserve A. sys[ ( -- ) A bindalloc of SYSALLOC. Useful when you want to make sure you're allocating memory from the system. Usually used in allocators themselves. entry+ ( payloadsz 'dict str -- payload ) Create a new dictionary entry with expected payload size of "payloadsz" bytes. We do so by reserving the appropriate amount of bytes before creating the entry. This guarantees contiguous memory. The yielded "payload" is the address of the "payload" part of the newly created entry, which has already been allocated (don't allocate it again!).