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  }