2016-05-08 12:33:17 +02:00
|
|
|
// Copyright 2016 by Sascha L. Teichmann
|
|
|
|
// Use of this source code is governed by the MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2016-05-10 18:57:14 +02:00
|
|
|
const btMaxEntries = 256
|
|
|
|
|
|
|
|
type btKey struct {
|
|
|
|
x int
|
|
|
|
y int
|
|
|
|
}
|
|
|
|
|
|
|
|
type btHashEntry struct {
|
|
|
|
prev *btHashEntry
|
|
|
|
next *btHashEntry
|
|
|
|
hash []byte
|
|
|
|
btKey
|
|
|
|
}
|
|
|
|
|
2016-05-08 12:33:17 +02:00
|
|
|
type BaseTileHash struct {
|
2016-05-10 18:57:14 +02:00
|
|
|
hashes map[btKey]*btHashEntry
|
|
|
|
root btHashEntry
|
2016-05-08 12:33:17 +02:00
|
|
|
sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBaseTileHash() *BaseTileHash {
|
2016-05-10 18:57:14 +02:00
|
|
|
bth := &BaseTileHash{
|
|
|
|
hashes: map[btKey]*btHashEntry{}}
|
|
|
|
bth.root.next = &bth.root
|
|
|
|
bth.root.prev = &bth.root
|
|
|
|
return bth
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bth *BaseTileHash) toFront(entry *btHashEntry) {
|
|
|
|
if bth.root.next == entry {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
entry.prev.next = entry.next
|
|
|
|
entry.next.prev = entry.prev
|
|
|
|
entry.next = bth.root.next
|
|
|
|
entry.prev = &bth.root
|
|
|
|
bth.root.next = entry
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bth *BaseTileHash) removeLast() *btHashEntry {
|
|
|
|
last := bth.root.prev
|
|
|
|
bth.root.prev = last.prev
|
|
|
|
last.prev.next = &bth.root
|
|
|
|
delete(bth.hashes, last.btKey)
|
|
|
|
return last
|
|
|
|
}
|
|
|
|
|
|
|
|
func (bth *BaseTileHash) insertFront(entry *btHashEntry) {
|
|
|
|
entry.next = bth.root.next
|
|
|
|
entry.prev = &bth.root
|
|
|
|
bth.root.next.prev = entry
|
|
|
|
bth.root.next = entry
|
2016-05-08 12:33:17 +02:00
|
|
|
}
|
|
|
|
|
2016-05-08 17:33:51 +02:00
|
|
|
func (bth *BaseTileHash) Update(x, y int, hash []byte) bool {
|
2016-05-08 12:33:17 +02:00
|
|
|
bth.Lock()
|
|
|
|
defer bth.Unlock()
|
2016-05-10 18:57:14 +02:00
|
|
|
key := btKey{x, y}
|
2016-05-08 12:33:17 +02:00
|
|
|
if old, found := bth.hashes[key]; found {
|
2016-05-10 18:57:14 +02:00
|
|
|
if !bytes.Equal(old.hash, hash) {
|
|
|
|
old.hash = hash
|
|
|
|
bth.toFront(old)
|
2016-05-08 17:22:04 +02:00
|
|
|
return true
|
2016-05-08 12:33:17 +02:00
|
|
|
}
|
2016-05-08 17:22:04 +02:00
|
|
|
return false
|
2016-05-08 12:33:17 +02:00
|
|
|
}
|
2016-05-10 18:57:14 +02:00
|
|
|
var entry *btHashEntry
|
|
|
|
if len(bth.hashes) >= btMaxEntries {
|
|
|
|
entry = bth.removeLast()
|
|
|
|
} else {
|
|
|
|
entry = new(btHashEntry)
|
|
|
|
}
|
|
|
|
entry.btKey = key
|
|
|
|
entry.hash = hash
|
|
|
|
bth.hashes[key] = entry
|
|
|
|
bth.insertFront(entry)
|
2016-05-08 12:33:17 +02:00
|
|
|
return true
|
|
|
|
}
|