Added Low level type erasure to Vecs - #4
Conversation
|
|
||
| template checkNotATuple[T](tup: typedesc[T]) = | ||
| when T is tuple: | ||
| when T is tuple and not defined(danger): |
There was a problem hiding this comment.
when T is tuple is a compile time check, should not be skipped with -d:danger as it would allow compiling with an invalid type.
| archetypeIds: seq[ArchetypeId] = @[] | ||
| archetypes: Table[ArchetypeId, Archetype] | ||
| builders: seq[Builder] | ||
| movers: seq[Mover] |
There was a problem hiding this comment.
Remove lingering World.movers field.
There was a problem hiding this comment.
(also remove world.movers.setLen(id + 1) set down below)
| proc `==`*(a, b: ComponentId): bool {.borrow.} | ||
| proc `$`*(id: ComponentId): string = $id.int | ||
| template `[]`*[T](s: seq[T], i:ComponentId): T = s[i.int] | ||
| template `[]=`*[T](s: seq[T], i:ComponentId, val: T) = (s[i.int] = v) |
There was a problem hiding this comment.
Param is val, but is used as v, won't compile when used.
|
|
||
| type Adder* = | ||
| proc(ecsSeq: var EcsSeqAny): int | ||
| proc(ecsSeq: var EcsSeqAny, itemPtr: pointer): int {.nimcall.} |
There was a problem hiding this comment.
Adder type is dead, remove it.
|
|
||
|
|
||
| type Mover* = | ||
| proc(fromEcsSeq: var EcsSeqAny, index: int, toEcsSeq: var EcsSeqAny): int {.nimcall.} |
|
|
||
| proc ecsSeqAdder*[T](): Adder = | ||
| proc(ecsSeq: var EcsSeqAny, itemPtr: pointer): int {.nimcall.} = | ||
| cast[EcsSeq[T]](ecsSeq).add cast[ptr T](itemPtr)[] |
There was a problem hiding this comment.
ecsSeqAdder is now dead code, remove it
| fromEcsSeq.del index | ||
| result = typedToEcsSeq.add element | ||
| result = typedTo.add element | ||
| ]# |
There was a problem hiding this comment.
ecsSeqMover is commented code, remove it
| componentIds*: seq[ComponentId] | ||
| componentLists*: Table[ComponentId, EcsSeqAny] | ||
| componentLists*: seq[EcsSeqAny] | ||
| componentSequences: seq[EcsSeqAny] |
There was a problem hiding this comment.
What do you think about renaming these?
componentLists -> sparseComponents
componentSeqs -> denseComponents
| id*: ArchetypeId | ||
| componentIds*: seq[ComponentId] | ||
| componentLists*: Table[ComponentId, EcsSeqAny] | ||
| componentLists*: seq[EcsSeqAny] |
There was a problem hiding this comment.
show.nim:29 calls archetype.componentLists.hasKey(componentId), leftover from when it was a Table
| proc isEmpty*(archetype: Archetype): bool = | ||
| for componentList in archetype.componentLists.values: | ||
| for componentList in archetype.componentLists: | ||
| return componentList.len == 0 |
There was a problem hiding this comment.
use the dense one: componentSequences[0].len == 0
| dealloc(s.data) | ||
| s.data = nil | ||
| s.len = 0 | ||
| s.cap = 0 |
There was a problem hiding this comment.
vseq.nim:31-37: =destroy does zeroMem + dealloc on the buffer without ever running element destructors, this is a leak (seq[T] does that). Also check setLen, del, clear, shrink, =copy and =dup, zeroing elements that may contain a ref, or copying without updating refcounts.
Purpose
This PR's purpose is to implement unsafe type erasure for
vecs, without using closures and virtual calls.This allows for raw access between components pool of different type without cost.
What was done
vseq.nim: It implementseqbut with unsafe operations allowing unsafe access without using the type. It was favored over Nim'sseqbecause its layout varies with versionsecsseq.nim: To use the newVSeqtype, and have type erased operations, without closuresarchetypes.nim: Removed theaddersandmovers, use raw byte manipulation functions. Also removedTables in favor of rawseqsworld.nim: Made the Immediate case no more use closure, it now has his own code path and for faster operations. Also, replaced adders with raw byte sequences (with their source zeroed, making it act as a move) that will be managed with the unsafe operationsWhat can be explored further
reftypes