size = capacity * (sizeof(Bitmap) + sizeof(Keys) + sizeof(Values))
_HashedContainerStorageHeader (struct)
maxLoadFactorInverse
is a coefficient that allows the buffer to be expanded if necessary._NativeDictionaryStorageImpl<Key, Value> (class)
ManagedBuffer<_HashedContainerStorageHeader, UInt8>
internal var _values: UnsafeMutablePointer<Value> { @warn_unused_result get { let start = UInt(Builtin.ptrtoint_Word(_keys._rawValue)) &+ UInt(_capacity) &* UInt(strideof(Key.self)) let alignment = UInt(alignof(Value)) let alignMask = alignment &- UInt(1) return UnsafeMutablePointer<Value>( bitPattern:(start &+ alignMask) & ~alignMask) } }
internal class func create(capacity: Int) -> StorageImpl { let requiredCapacity = bytesForBitMap(capacity) + bytesForKeys(capacity) + bytesForValues(capacity) let r = super.create(requiredCapacity) { _ in return _HashedContainerStorageHeader(capacity: capacity) } let storage = r as! StorageImpl let initializedEntries = _BitMap( storage: storage._initializedHashtableEntriesBitMapStorage, bitCount: capacity) initializedEntries.initializeToZero() return storage }
// : , ,
// (: Hashable) -
// , Hashable.
_NativeDictionaryStorage<Key : Hashable, Value> ()
@warn_unused_result internal func _bucket(k: Key) -> Int { return _squeezeHashValue(k.hashValue, 0..<capacity) }
_next
and _prev
. Capacity is always a number that can be expressed in binary. If we are at the end of the segment array, if desired, the rollback to the initial position is specified via the _next
call. internal var _bucketMask: Int { // The capacity is not negative, therefore subtracting 1 will not overflow. return capacity &- 1 } @warn_unused_result internal func _next(bucket: Int) -> Int { // Bucket is within 0 and capacity. Therefore adding 1 does not overflow. return (bucket &+ 1) & _bucketMask } @warn_unused_result internal func _prev(bucket: Int) -> Int { // Bucket is not negative. Therefore subtracting 1 does not overflow. return (bucket &- 1) & _bucketMask }
@_transparent internal func initializeKey(k: Key, value v: Value, at i: Int) { _sanityCheck(!isInitializedEntry(i)) (keys + i).initialize(k) (values + i).initialize(v) initializedEntries[i] = true _fixLifetime(self) }
_find
function_bucket(key)
; /// . /// /// , /// . @warn_unused_result internal func _find(key: Key, _ startBucket: Int) -> (pos: Index, found: Bool) { var bucket = startBucket // The invariant guarantees there's always a hole, so we just loop // until we find one while true { let isHole = !isInitializedEntry(bucket) if isHole { return (Index(nativeStorage: self, offset: bucket), false) } if keyAt(bucket) == key { return (Index(nativeStorage: self, offset: bucket), true) } bucket = _next(bucket) } }
_BitMap
struct is used as a wrapper that allows reading and writing to bitmap._NativeDictionaryStorageOwner (class)
_VariantDictionaryStorage<Key : Hashable, Value> ( )
case Native(_NativeDictionaryStorageOwner<Key, Value>) case Cocoa(_CocoaDictionaryStorage)
/// - idealBucket: , . /// - offset: , . /// . internal mutating func nativeDeleteImpl( nativeStorage: NativeStorage, idealBucket: Int, offset: Int ) { _sanityCheck( nativeStorage.isInitializedEntry(offset), "expected initialized entry") // nativeStorage.destroyEntryAt(offset) nativeStorage.count -= 1 // , // . var hole = offset // var start = idealBucket while nativeStorage.isInitializedEntry(nativeStorage._prev(start)) { start = nativeStorage._prev(start) } // var lastInChain = hole var b = nativeStorage._next(lastInChain) while nativeStorage.isInitializedEntry(b) { lastInChain = b b = nativeStorage._next(b) } // , , , // . while hole != lastInChain { // , // , . var b = lastInChain while b != hole { let idealBucket = nativeStorage._bucket(nativeStorage.keyAt(b)) // ? // [, ] // let c0 = idealBucket >= start let c1 = idealBucket <= hole if start <= hole ? (c0 && c1) : (c0 || c1) { break // Found it } b = nativeStorage._prev(b) } if b == hole { // No out-of-place elements found; we're done adjusting break } // nativeStorage.moveInitializeFrom(nativeStorage, at: b, toEntryAt: hole) hole = b } }
Source: https://habr.com/ru/post/275911/
All Articles