Reusable-key storage for values of one schema with direct lookup by numeric key and live-entry iteration.
A pool schema is constructed by placing one item schema in front of the module name after "Pool" use, for example Int32 Pool.
POOL: pool marker field.Item: stored item schema.entrySize: storage size reserved per entry.data: storage for the entry area.dataSize: allocated entry count.firstFree: first reusable key, or -1 when no reusable key is available.exactAllocatedMemSize: currently allocated byte count.iter (-- iter): iterates {key value} pairs.keys (-- iter): iterates keys only.values (-- iter): iterates values only.getSize (-- count) and size (-- count): return the allocated entry count, not the number of live items.at (key -- ref): returns Ref to the item at one valid key.valid (key -- valid): reports whether one key currently identifies a live entry.firstValid (-- key) and nextValid (key -- nextKey): locate live keys.getNextIndex (-- key): returns the next insertion key.insert (item -- key): inserts one item and returns its key.erase (key --): destroys the item at key and returns that key to the reusable-key list.clear (--): destroys all live items and keeps the allocated storage.Destroying the pool variable releases any remaining allocated storage.
Int32 values.0.insert uses firstFree when one reusable key exists. Otherwise it uses the next new key.size and getSize are allocation-size queries, not live-item count queries.valid asserts that the supplied key is in range, then reports whether that key identifies a live entry.at requires one valid key.firstValid returns the first live key, or size when no live key exists.nextValid returns the next live key after the supplied key, or size when no later live key exists.iter, keys, and values traverse live entries in ascending numeric key order and skip freed entries.The following helpers expose the underlying entry area and validity-bit storage directly:
getAddressByIndex (key -- address)getTailAddressByIndex (key -- address)elementAt (key -- ref)nextFreeAt (key -- ref)validAt (key -- ref)These helpers do not replace the validity rules described above. at, valid, firstValid, and nextValid remain the ordinary key-facing interface.
The next methods of iter, keys, and values return one produced item together with one success condition.
iter.next (-- pair valid) returns one {key value} record and one Cond.keys.next (-- key valid) returns one key and one Cond.values.next (-- value valid) returns one value and one Cond."Pool" use
"control" use
{} () {} [
p: Int32 Pool;
@p.iter.next printStack swap drop drop
@p.keys.next printStack swap drop drop
@p.values.next printStack swap drop drop
] "main" exportFunction
{
key: 0;
value: Int32 NIL;
}
FALSE
0
FALSE
Int32 NIL
FALSE
"Pool" use
"String" use
"control" use
{} Int32 {} [
p: Int32 Pool;
k0: 5 @p.insert;
k1: 6 @p.insert;
("k0=" k0 LF
"k1=" k1 LF
"value0=" k0 @p.at new LF) printList
k0 @p.erase
("next=" p.getNextIndex LF) printList
0
] "main" exportFunction
k0=0
k1=1
value0=5
next=0
"Pool" use
"String" use
"control" use
{} Int32 {} [
p: Int32 Pool;
10 @p.insert drop
20 @p.insert drop
0 @p.erase
30 @p.insert drop
pairs: @p.iter;
pair0: ok0: @pairs.next;;
pair1: ok1: @pairs.next;;
pair2: ok2: @pairs.next;;
keys: @p.keys;
key0: hasKey0: @keys.next;;
key1: hasKey1: @keys.next;;
values: @p.values;
value0: hasValue0: @values.next;;
value1: hasValue1: @values.next;;
("iter0Key=" pair0.key LF
"iter0Value=" pair0.value new LF
"iter1Key=" pair1.key LF
"iter1Value=" pair1.value new LF
"iterDone=" ok2 LF
"key0=" key0 LF
"key1=" key1 LF
"value0=" value0 new LF
"value1=" value1 new LF
"size=" @p.size LF) printList
0
] "main" exportFunction
iter0Key=0
iter0Value=30
iter1Key=1
iter1Value=20
iterDone=FALSE
key0=0
key1=1
value0=30
value1=20
size=8
"Pool" use
"String" use
"control" use
{} Int32 {} [
p: Int32 Pool;
10 @p.insert drop
20 @p.insert drop
30 @p.insert drop
1 @p.erase
("valid0=" 0 @p.valid LF
"valid1=" 1 @p.valid LF
"first=" p.firstValid LF
"next0=" 0 @p.nextValid LF
"next2=" 2 @p.nextValid LF) printList
0
] "main" exportFunction
valid0=TRUE
valid1=FALSE
first=0
next0=2
next2=8