Refine entity identifier generator

This commit is contained in:
Christian Treffs 2020-08-21 10:53:32 +02:00
parent af81c88a51
commit fcf5f4eaf3
No known key found for this signature in database
GPG Key ID: 49A4B4B460BE3ED4
1 changed files with 23 additions and 19 deletions

View File

@ -5,18 +5,23 @@
// Created by Christian Treffs on 26.06.20.
//
/// An entity identifier generator provides new entity
/// identifiers on entity creation.
/// It also allows entity ids to be marked for re-use.
/// Entity identifiers must be unique.
/// **Entity Identifier Generator**
///
/// An entity identifier generator provides new entity identifiers on entity creation.
/// It also allows entity ids to be marked as unused (to be re-usable).
///
/// You should strive to keep entity ids tightly packed around `EntityIdentifier.Identifier.min` since it has an influence on the underlying memory layout.
public protocol EntityIdentifierGenerator {
/// Initialize the generator with entity ids already in use.
/// - Parameter entityIds: The entity ids already in use. Default should be an empty array.
init(inUse entityIds: [EntityIdentifier])
/// Initialize the generator providing entity ids to begin with when creating new entities.
///
/// Entity ids provided should be passed to `nextId()` in last out order up until the collection is empty.
/// The default is an empty collection.
/// - Parameter initialEntityIds: The entity ids to start providing up until the collection is empty (in last out order).
init<EntityIds>(startProviding initialEntityIds: EntityIds) where EntityIds: BidirectionalCollection, EntityIds.Element == EntityIdentifier
/// Provides the next unused entity identifier.
///
/// The provided entity identifier is at least unique during runtime.
/// The provided entity identifier must be unique during runtime.
func nextId() -> EntityIdentifier
/// Marks the given entity identifier as free and ready for re-use.
@ -36,8 +41,8 @@ public struct DefaultEntityIdGenerator: EntityIdentifierGenerator {
@usableFromInline var count: Int { stack.count }
@usableFromInline
init(inUse entityIds: [EntityIdentifier]) {
stack = entityIds.reversed().map(\.id)
init<EntityIds>(startProviding initialEntityIds: EntityIds) where EntityIds: BidirectionalCollection, EntityIds.Element == EntityIdentifier {
stack = initialEntityIds.map { $0.id }
}
@usableFromInline
@ -57,25 +62,24 @@ public struct DefaultEntityIdGenerator: EntityIdentifierGenerator {
}
@usableFromInline let storage: Storage
@usableFromInline var count: Int { storage.count }
@inlinable
public init<EntityIds>(startProviding initialEntityIds: EntityIds) where EntityIds: BidirectionalCollection, EntityIds.Element == EntityIdentifier {
self.storage = Storage(startProviding: initialEntityIds)
}
@inlinable
public init() {
self.init(inUse: [EntityIdentifier(0)])
self.init(startProviding: [EntityIdentifier(0)])
}
@inlinable
public init(inUse entityIds: [EntityIdentifier]) {
self.storage = Storage(inUse: entityIds)
}
@inlinable
@inline(__always)
public func nextId() -> EntityIdentifier {
storage.nextId()
}
@inlinable
@inline(__always)
public func markUnused(entityId: EntityIdentifier) {
storage.markUnused(entityId: entityId)
}