github.com/xg0n/routine@v0.0.0-20240119033701-c364deb94aee/thread_local_map.go (about) 1 package routine 2 3 var unset entry = &object{} 4 5 type object struct { 6 none bool //nolint:unused 7 } 8 9 type threadLocalMap struct { 10 table []entry 11 } 12 13 func (mp *threadLocalMap) get(index int) entry { 14 lookup := mp.table 15 if index < len(lookup) { 16 return lookup[index] 17 } 18 return unset 19 } 20 21 func (mp *threadLocalMap) set(index int, value entry) { 22 lookup := mp.table 23 if index < len(lookup) { 24 lookup[index] = value 25 return 26 } 27 mp.expandAndSet(index, value) 28 } 29 30 func (mp *threadLocalMap) remove(index int) { 31 lookup := mp.table 32 if index < len(lookup) { 33 lookup[index] = unset 34 } 35 } 36 37 func (mp *threadLocalMap) expandAndSet(index int, value entry) { 38 oldArray := mp.table 39 oldCapacity := len(oldArray) 40 newCapacity := index 41 newCapacity |= newCapacity >> 1 42 newCapacity |= newCapacity >> 2 43 newCapacity |= newCapacity >> 4 44 newCapacity |= newCapacity >> 8 45 newCapacity |= newCapacity >> 16 46 newCapacity++ 47 48 newArray := make([]entry, newCapacity) 49 copy(newArray, oldArray) 50 fill(newArray, oldCapacity, newCapacity, unset) 51 newArray[index] = value 52 mp.table = newArray 53 } 54 55 func createInheritedMap() *threadLocalMap { 56 parent := currentThread(false) 57 if parent == nil { 58 return nil 59 } 60 parentMap := parent.inheritableThreadLocals 61 if parentMap == nil { 62 return nil 63 } 64 lookup := parentMap.table 65 if lookup == nil { 66 return nil 67 } 68 table := make([]entry, len(lookup)) 69 copy(table, lookup) 70 for i := 0; i < len(table); i++ { 71 if c, ok := entryAssert[Cloneable](table[i]); ok { 72 table[i] = entry(c.Clone()) 73 } 74 } 75 return &threadLocalMap{table: table} 76 } 77 78 func fill[T any](a []T, fromIndex int, toIndex int, val T) { 79 for i := fromIndex; i < toIndex; i++ { 80 a[i] = val 81 } 82 }