gosora/experimental/counterTree/tree.go

77 lines
1.7 KiB
Go

package main
import (
"fmt"
"math/bits"
"sync/atomic"
"unsafe"
)
const debug = true
type TreeCounterNode struct {
Value uint64
Zero *TreeCounterNode
One *TreeCounterNode
Parent *TreeCounterNode
}
// MEGA EXPERIMENTAL. Start from the right-most bits in the integer and move leftwards
type TreeTopicViewCounter struct {
root *TreeCounterNode
}
func newTreeTopicViewCounter() *TreeTopicViewCounter {
return &TreeTopicViewCounter{
&TreeCounterNode{0, nil, nil, nil},
}
}
func (counter *TreeTopicViewCounter) Bump(signTopicID int64) {
var topicID uint64 = uint64(signTopicID)
var zeroCount = bits.LeadingZeros64(topicID)
if debug {
fmt.Printf("topicID int64: %d\n", signTopicID)
fmt.Printf("topicID int64: %x\n", signTopicID)
fmt.Printf("topicID int64: %b\n", signTopicID)
fmt.Printf("topicID uint64: %b\n", topicID)
fmt.Printf("leading zeroes: %d\n", zeroCount)
var leadingZeroes = ""
for i := 0; i < zeroCount; i++ {
leadingZeroes += "0"
}
fmt.Printf("topicID lead uint64: %s%b\n", leadingZeroes, topicID)
fmt.Printf("---\n")
}
var stopAt uint64 = 64 - uint64(zeroCount)
var spot uint64 = 1
var node = counter.root
for {
if debug {
fmt.Printf("spot: %d\n", spot)
fmt.Printf("topicID&spot: %d\n", topicID&spot)
}
if topicID&spot == 1 {
if node.One == nil {
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(node.One)), nil, unsafe.Pointer(&TreeCounterNode{0, nil, nil, node}))
}
node = node.One
} else {
if node.Zero == nil {
atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(node.Zero)), nil, unsafe.Pointer(&TreeCounterNode{0, nil, nil, node}))
}
node = node.Zero
}
spot++
if spot >= stopAt {
break
}
}
atomic.AddUint64(&node.Value, 1)
}