77 lines
1.7 KiB
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)
|
||
|
}
|