github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/experimental/counterTree/tree.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "math/bits" 6 "sync/atomic" 7 "unsafe" 8 ) 9 10 const debug = true 11 12 type TreeCounterNode struct { 13 Value uint64 14 Zero *TreeCounterNode 15 One *TreeCounterNode 16 Parent *TreeCounterNode 17 } 18 19 // MEGA EXPERIMENTAL. Start from the right-most bits in the integer and move leftwards 20 type TreeTopicViewCounter struct { 21 root *TreeCounterNode 22 } 23 24 func newTreeTopicViewCounter() *TreeTopicViewCounter { 25 return &TreeTopicViewCounter{ 26 &TreeCounterNode{0, nil, nil, nil}, 27 } 28 } 29 30 func (counter *TreeTopicViewCounter) Bump(signTopicID int64) { 31 var topicID uint64 = uint64(signTopicID) 32 var zeroCount = bits.LeadingZeros64(topicID) 33 if debug { 34 fmt.Printf("topicID int64: %d\n", signTopicID) 35 fmt.Printf("topicID int64: %x\n", signTopicID) 36 fmt.Printf("topicID int64: %b\n", signTopicID) 37 fmt.Printf("topicID uint64: %b\n", topicID) 38 fmt.Printf("leading zeroes: %d\n", zeroCount) 39 40 var leadingZeroes = "" 41 for i := 0; i < zeroCount; i++ { 42 leadingZeroes += "0" 43 } 44 fmt.Printf("topicID lead uint64: %s%b\n", leadingZeroes, topicID) 45 46 fmt.Printf("---\n") 47 } 48 49 var stopAt uint64 = 64 - uint64(zeroCount) 50 var spot uint64 = 1 51 var node = counter.root 52 for { 53 if debug { 54 fmt.Printf("spot: %d\n", spot) 55 fmt.Printf("topicID&spot: %d\n", topicID&spot) 56 } 57 if topicID&spot == 1 { 58 if node.One == nil { 59 atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(node.One)), nil, unsafe.Pointer(&TreeCounterNode{0, nil, nil, node})) 60 } 61 node = node.One 62 } else { 63 if node.Zero == nil { 64 atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(node.Zero)), nil, unsafe.Pointer(&TreeCounterNode{0, nil, nil, node})) 65 } 66 node = node.Zero 67 } 68 69 spot++ 70 if spot >= stopAt { 71 break 72 } 73 } 74 75 atomic.AddUint64(&node.Value, 1) 76 }