diff --git a/go.mod b/go.mod index 7a2417445e102b8befa95b29d42d328c92c0497b..7441bd9876e53d14abac1ce107f2fa2f79bc7da0 100644 --- a/go.mod +++ b/go.mod @@ -7,11 +7,10 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgryski/go-farm v0.0.0-20191112170834-c2139c5d712b // indirect github.com/gdamore/tcell v1.3.0 - github.com/go-zeromq/zmq4 v0.7.0 github.com/golang/protobuf v1.3.2 github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2 github.com/googollee/go-socket.io v1.4.3-0.20191204093753-683f8725b6d0 - github.com/gorilla/websocket v1.4.1 + github.com/gorilla/websocket v1.4.1 // indirect github.com/iotaledger/hive.go v0.0.0-20200121213505-28904d5f037c github.com/iotaledger/iota.go v1.0.0-beta.14 github.com/labstack/echo v3.3.10+incompatible @@ -35,9 +34,7 @@ require ( go.uber.org/zap v1.13.0 golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 // indirect - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect gopkg.in/ini.v1 v1.51.1 // indirect gopkg.in/yaml.v2 v2.2.7 // indirect ) diff --git a/go.sum b/go.sum index 47bfbc4884977d5de44ead02f5e46e48cb57ceaa..90d5e02bf72407b449872df2981467cc64b3fcab 100644 --- a/go.sum +++ b/go.sum @@ -64,10 +64,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-zeromq/goczmq/v4 v4.2.2 h1:HAJN+i+3NW55ijMJJhk7oWxHKXgAuSBkoFfvr8bYj4U= -github.com/go-zeromq/goczmq/v4 v4.2.2/go.mod h1:Sm/lxrfxP/Oxqs0tnHD6WAhwkWrx+S+1MRrKzcxoaYE= -github.com/go-zeromq/zmq4 v0.7.0 h1:tmmTVfWB0HYo+8Ra0DK2MJIDl1lsvuU/J9559hpLU7s= -github.com/go-zeromq/zmq4 v0.7.0/go.mod h1:fo1rWyfV/bsg7tq/F9LF1H0e2Cf3ovQFoge1G21AnWU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -343,8 +339,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -386,8 +380,6 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= diff --git a/packages/datastructure/doubly_linked_list.go b/packages/datastructure/doubly_linked_list.go deleted file mode 100644 index bc511e3f0fd126afe40879a964d5cc00f521072a..0000000000000000000000000000000000000000 --- a/packages/datastructure/doubly_linked_list.go +++ /dev/null @@ -1,265 +0,0 @@ -package datastructure - -import ( - "fmt" - "sync" -) - -type DoublyLinkedList struct { - head *DoublyLinkedListEntry - tail *DoublyLinkedListEntry - count int - mutex sync.RWMutex -} - -// region public methods with locking ////////////////////////////////////////////////////////////////////////////////// - -// Appends the specified value to the end of this list. -func (list *DoublyLinkedList) Add(value interface{}) *DoublyLinkedListEntry { - return list.AddLast(value) -} - -// Appends the specified element to the end of this list. -func (list *DoublyLinkedList) AddEntry(entry *DoublyLinkedListEntry) { - list.AddLastEntry(entry) -} - -func (list *DoublyLinkedList) AddLast(value interface{}) *DoublyLinkedListEntry { - newEntry := &DoublyLinkedListEntry{ - value: value, - } - - list.AddLastEntry(newEntry) - - return newEntry -} - -func (list *DoublyLinkedList) AddLastEntry(entry *DoublyLinkedListEntry) { - list.mutex.Lock() - defer list.mutex.Unlock() - - list.addLastEntry(entry) -} - -func (list *DoublyLinkedList) AddFirst(value interface{}) *DoublyLinkedListEntry { - newEntry := &DoublyLinkedListEntry{ - value: value, - } - - list.AddFirstEntry(newEntry) - - return newEntry -} - -func (list *DoublyLinkedList) AddFirstEntry(entry *DoublyLinkedListEntry) { - list.mutex.Lock() - defer list.mutex.Unlock() - - list.addFirstEntry(entry) -} - -func (list *DoublyLinkedList) Clear() { - list.mutex.Lock() - defer list.mutex.Unlock() - - list.clear() -} - -func (list *DoublyLinkedList) GetFirst() (interface{}, error) { - if firstEntry, err := list.GetFirstEntry(); err != nil { - return nil, err - } else { - return firstEntry.GetValue(), nil - } -} - -func (list *DoublyLinkedList) GetFirstEntry() (*DoublyLinkedListEntry, error) { - list.mutex.RLock() - defer list.mutex.RUnlock() - - return list.getFirstEntry() -} - -func (list *DoublyLinkedList) GetLast() (interface{}, error) { - if lastEntry, err := list.GetLastEntry(); err != nil { - return nil, err - } else { - return lastEntry.GetValue(), nil - } -} - -func (list *DoublyLinkedList) GetLastEntry() (*DoublyLinkedListEntry, error) { - list.mutex.RLock() - defer list.mutex.RUnlock() - - return list.getLastEntry() -} - -func (list *DoublyLinkedList) RemoveFirst() (interface{}, error) { - if firstEntry, err := list.RemoveFirstEntry(); err != nil { - return nil, err - } else { - return firstEntry.GetValue(), nil - } -} - -func (list *DoublyLinkedList) RemoveFirstEntry() (*DoublyLinkedListEntry, error) { - list.mutex.Lock() - defer list.mutex.Unlock() - - return list.removeFirstEntry() -} - -func (list *DoublyLinkedList) RemoveLast() (interface{}, error) { - if lastEntry, err := list.RemoveLastEntry(); err != nil { - return nil, err - } else { - return lastEntry.GetValue(), nil - } -} - -func (list *DoublyLinkedList) RemoveLastEntry() (*DoublyLinkedListEntry, error) { - list.mutex.Lock() - defer list.mutex.Unlock() - - return list.removeLastEntry() -} - -func (list *DoublyLinkedList) Remove(value interface{}) error { - list.mutex.RLock() - currentEntry := list.head - for currentEntry != nil { - if currentEntry.GetValue() == value { - list.mutex.RUnlock() - - if err := list.RemoveEntry(currentEntry); err != nil { - return err - } - - return nil - } - - currentEntry = currentEntry.GetNext() - } - list.mutex.RUnlock() - - return fmt.Errorf("%w: the entry is not part of the list", ErrNoSuchElement) -} - -func (list *DoublyLinkedList) RemoveEntry(entry *DoublyLinkedListEntry) error { - list.mutex.Lock() - defer list.mutex.Unlock() - - return list.removeEntry(entry) -} - -func (list *DoublyLinkedList) GetSize() int { - list.mutex.RLock() - defer list.mutex.RUnlock() - - return list.count -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// region private methods without locking ////////////////////////////////////////////////////////////////////////////// - -func (list *DoublyLinkedList) addLastEntry(entry *DoublyLinkedListEntry) { - if list.head == nil { - list.head = entry - } else { - list.tail.SetNext(entry) - entry.SetPrev(list.tail) - } - - list.tail = entry - list.count++ -} - -func (list *DoublyLinkedList) addFirstEntry(entry *DoublyLinkedListEntry) { - if list.tail == nil { - list.tail = entry - } else { - list.head.SetPrev(entry) - entry.SetNext(list.head) - } - - list.head = entry - list.count++ -} - -func (list *DoublyLinkedList) clear() { - list.head = nil - list.tail = nil - list.count = 0 -} - -func (list *DoublyLinkedList) getFirstEntry() (*DoublyLinkedListEntry, error) { - if list.head == nil { - return nil, fmt.Errorf("%w: the list is empty", ErrNoSuchElement) - } - - return list.head, nil -} - -func (list *DoublyLinkedList) getLastEntry() (*DoublyLinkedListEntry, error) { - if list.tail == nil { - return nil, fmt.Errorf("%w: the list is empty", ErrNoSuchElement) - } - - return list.tail, nil -} - -func (list *DoublyLinkedList) removeFirstEntry() (*DoublyLinkedListEntry, error) { - entryToRemove := list.head - if err := list.removeEntry(entryToRemove); err != nil { - return nil, err - } - - return entryToRemove, nil -} - -func (list *DoublyLinkedList) removeLastEntry() (*DoublyLinkedListEntry, error) { - entryToRemove := list.tail - if err := list.removeEntry(entryToRemove); err != nil { - return nil, err - } - - return entryToRemove, nil -} - -func (list *DoublyLinkedList) removeEntry(entry *DoublyLinkedListEntry) error { - if entry == nil { - return fmt.Errorf("%w: the entry must not be nil", ErrInvalidArgument) - } - - if list.head == nil { - return fmt.Errorf("%w: the entry is not part of the list", ErrNoSuchElement) - } - - prevEntry := entry.GetPrev() - nextEntry := entry.GetNext() - - if nextEntry != nil { - nextEntry.SetPrev(prevEntry) - } - if list.head == entry { - list.head = nextEntry - } - - if prevEntry != nil { - prevEntry.SetNext(nextEntry) - } - if list.tail == entry { - list.tail = prevEntry - } - - entry.SetNext(nil) - entry.SetPrev(nil) - - list.count-- - - return nil -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/datastructure/doubly_linked_list_entry.go b/packages/datastructure/doubly_linked_list_entry.go deleted file mode 100644 index 73c05b2964d2bf4b2400e91f60977d327b8ae4ec..0000000000000000000000000000000000000000 --- a/packages/datastructure/doubly_linked_list_entry.go +++ /dev/null @@ -1,54 +0,0 @@ -package datastructure - -import ( - "sync" -) - -type DoublyLinkedListEntry struct { - value interface{} - prev *DoublyLinkedListEntry - next *DoublyLinkedListEntry - mutex sync.RWMutex -} - -func (entry *DoublyLinkedListEntry) GetNext() *DoublyLinkedListEntry { - entry.mutex.RLock() - defer entry.mutex.RUnlock() - - return entry.next -} - -func (entry *DoublyLinkedListEntry) SetNext(next *DoublyLinkedListEntry) { - entry.mutex.Lock() - defer entry.mutex.Unlock() - - entry.next = next -} - -func (entry *DoublyLinkedListEntry) GetPrev() *DoublyLinkedListEntry { - entry.mutex.RLock() - defer entry.mutex.RUnlock() - - return entry.prev -} - -func (entry *DoublyLinkedListEntry) SetPrev(prev *DoublyLinkedListEntry) { - entry.mutex.Lock() - defer entry.mutex.Unlock() - - entry.prev = prev -} - -func (entry *DoublyLinkedListEntry) GetValue() interface{} { - entry.mutex.RLock() - defer entry.mutex.RUnlock() - - return entry.value -} - -func (entry *DoublyLinkedListEntry) SetValue(value interface{}) { - entry.mutex.Lock() - defer entry.mutex.Unlock() - - entry.value = value -} diff --git a/packages/datastructure/doubly_linked_list_test.go b/packages/datastructure/doubly_linked_list_test.go deleted file mode 100644 index 7d43f0ce38cab6274d1b66352a6f6d5afe1799d1..0000000000000000000000000000000000000000 --- a/packages/datastructure/doubly_linked_list_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package datastructure - -import ( - "testing" -) - -func TestAdd(t *testing.T) { - doublyLinkedList := &DoublyLinkedList{} - - doublyLinkedList.Add(12) - doublyLinkedList.Add(12) - doublyLinkedList.Add(15) - doublyLinkedList.Add(99) - - if doublyLinkedList.GetSize() != 4 { - t.Error("the size of the list is wrong") - } -} - -func TestDelete(t *testing.T) { - doublyLinkedList := &DoublyLinkedList{} - - doublyLinkedList.Add(12) - doublyLinkedList.Add(13) - doublyLinkedList.Add(15) - doublyLinkedList.Add(99) - - if _, err := doublyLinkedList.RemoveFirst(); err != nil { - t.Error(err) - } - - if firstEntry, err := doublyLinkedList.GetFirst(); err != nil { - t.Error(err) - } else if firstEntry != 13 { - t.Error("first entry should be 13 after delete") - } - - if _, err := doublyLinkedList.RemoveLast(); err != nil { - t.Error(err) - } - - if lastEntry, err := doublyLinkedList.GetLast(); err != nil { - t.Error(err) - } else if lastEntry != 15 { - t.Error("last entry should be 15 after delete") - } - - if doublyLinkedList.GetSize() != 2 { - t.Error("the size of the list should be 2 after delete") - } -} diff --git a/packages/datastructure/errors.go b/packages/datastructure/errors.go deleted file mode 100644 index 757c2ef93eb188a3c6eac6410f948f84c6625070..0000000000000000000000000000000000000000 --- a/packages/datastructure/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package datastructure - -import ( - "errors" -) - -var ( - ErrNoSuchElement = errors.New("element does not exist") - ErrInvalidArgument = errors.New("invalid argument") -) diff --git a/packages/datastructure/krw_mutex.go b/packages/datastructure/krw_mutex.go deleted file mode 100644 index 2b05ce371275955fba2fdbb161f35ff58b37d107..0000000000000000000000000000000000000000 --- a/packages/datastructure/krw_mutex.go +++ /dev/null @@ -1,53 +0,0 @@ -package datastructure - -import ( - "sync" -) - -type KRWMutex struct { - keyMutexConsumers map[interface{}]int - keyMutexes map[interface{}]*sync.RWMutex - mutex sync.RWMutex -} - -func NewKRWMutex() *KRWMutex { - return &KRWMutex{ - keyMutexConsumers: make(map[interface{}]int), - keyMutexes: make(map[interface{}]*sync.RWMutex), - } -} - -func (krwMutex *KRWMutex) Register(key interface{}) (result *sync.RWMutex) { - krwMutex.mutex.Lock() - - if val, exists := krwMutex.keyMutexConsumers[key]; exists { - krwMutex.keyMutexConsumers[key] = val + 1 - result = krwMutex.keyMutexes[key] - } else { - result = &sync.RWMutex{} - - krwMutex.keyMutexConsumers[key] = 1 - krwMutex.keyMutexes[key] = result - } - - krwMutex.mutex.Unlock() - - return -} - -func (kwrMutex *KRWMutex) Free(key interface{}) { - kwrMutex.mutex.Lock() - - if val, exists := kwrMutex.keyMutexConsumers[key]; exists { - if val == 1 { - delete(kwrMutex.keyMutexConsumers, key) - delete(kwrMutex.keyMutexes, key) - } else { - kwrMutex.keyMutexConsumers[key] = val - 1 - } - } else { - panic("trying to free non-existent key") - } - - kwrMutex.mutex.Unlock() -} diff --git a/packages/datastructure/krw_mutex_test.go b/packages/datastructure/krw_mutex_test.go deleted file mode 100644 index bb5290aba7c4be3151e082edb4071611e4f664af..0000000000000000000000000000000000000000 --- a/packages/datastructure/krw_mutex_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package datastructure - -import ( - "testing" -) - -func TestKRWMutex_Free(t *testing.T) { - krwMutex := NewKRWMutex() - - krwMutex.Register("test") - krwMutex.Register("test") - krwMutex.Free("test") - krwMutex.Free("test") -} - -func BenchmarkKRWMutex(b *testing.B) { - krwMutex := NewKRWMutex() - - for i := 0; i < b.N; i++ { - krwMutex.Register(i) - krwMutex.Free(i) - } -} diff --git a/packages/datastructure/lru_cache.go b/packages/datastructure/lru_cache.go deleted file mode 100644 index fe15c424694b307b01e8a122864537e0057f74af..0000000000000000000000000000000000000000 --- a/packages/datastructure/lru_cache.go +++ /dev/null @@ -1,268 +0,0 @@ -package datastructure - -import ( - "sync" - - "github.com/iotaledger/hive.go/typeutils" -) - -type lruCacheElement struct { - key interface{} - value interface{} -} - -type LRUCache struct { - directory map[interface{}]*DoublyLinkedListEntry - doublyLinkedList *DoublyLinkedList - capacity int - size int - options *LRUCacheOptions - mutex sync.RWMutex - krwMutex KRWMutex -} - -func NewLRUCache(capacity int, options ...*LRUCacheOptions) *LRUCache { - var currentOptions *LRUCacheOptions - if len(options) < 1 || options[0] == nil { - currentOptions = DEFAULT_OPTIONS - } else { - currentOptions = options[0] - } - - return &LRUCache{ - directory: make(map[interface{}]*DoublyLinkedListEntry, capacity), - doublyLinkedList: &DoublyLinkedList{}, - capacity: capacity, - options: currentOptions, - krwMutex: KRWMutex{keyMutexConsumers: make(map[interface{}]int), keyMutexes: make(map[interface{}]*sync.RWMutex)}, - } -} - -func (cache *LRUCache) Set(key interface{}, value interface{}) { - keyMutex := cache.krwMutex.Register(key) - keyMutex.Lock() - - cache.mutex.Lock() - cache.set(key, value) - cache.mutex.Unlock() - - keyMutex.Unlock() - cache.krwMutex.Free(key) -} - -func (cache *LRUCache) set(key interface{}, value interface{}) { - directory := cache.directory - - if element, exists := directory[key]; exists { - element.value.(*lruCacheElement).value = value - - cache.promoteElement(element) - } else { - linkedListEntry := &DoublyLinkedListEntry{value: &lruCacheElement{key: key, value: value}} - - cache.doublyLinkedList.addFirstEntry(linkedListEntry) - directory[key] = linkedListEntry - - if cache.size == cache.capacity { - if element, err := cache.doublyLinkedList.removeLastEntry(); err != nil { - panic(err) - } else { - lruCacheElement := element.value.(*lruCacheElement) - removedElementKey := lruCacheElement.key - - delete(directory, removedElementKey) - - if cache.options.EvictionCallback != nil { - cache.options.EvictionCallback(removedElementKey, lruCacheElement.value) - } - } - } else { - cache.size++ - } - } -} - -func (cache *LRUCache) ComputeIfAbsent(key interface{}, callback func() interface{}) (result interface{}) { - keyMutex := cache.krwMutex.Register(key) - - keyMutex.RLock() - cache.mutex.RLock() - if element, exists := cache.directory[key]; exists { - cache.mutex.RUnlock() - cache.mutex.Lock() - cache.promoteElement(element) - cache.mutex.Unlock() - - result = element.GetValue().(*lruCacheElement).value - - keyMutex.RUnlock() - } else { - cache.mutex.RUnlock() - keyMutex.RUnlock() - keyMutex.Lock() - if result = callback(); !typeutils.IsInterfaceNil(result) { - cache.mutex.Lock() - cache.set(key, result) - cache.mutex.Unlock() - } - keyMutex.Unlock() - } - - cache.krwMutex.Free(key) - - return -} - -// Calls the callback if an entry with the given key exists. -// The result of the callback is written back into the cache. -// If the callback returns nil the entry is removed from the cache. -// Returns the updated entry. -func (cache *LRUCache) ComputeIfPresent(key interface{}, callback func(value interface{}) interface{}) (result interface{}) { - keyMutex := cache.krwMutex.Register(key) - - keyMutex.RLock() - cache.mutex.RLock() - if entry, exists := cache.directory[key]; exists { - cache.mutex.RUnlock() - keyMutex.RUnlock() - keyMutex.Lock() - - result = entry.GetValue().(*lruCacheElement).value - - if callbackResult := callback(result); !typeutils.IsInterfaceNil(callbackResult) { - result = callbackResult - - cache.mutex.Lock() - cache.set(key, callbackResult) - cache.mutex.Unlock() - - keyMutex.Unlock() - } else { - cache.mutex.Lock() - if err := cache.doublyLinkedList.removeEntry(entry); err != nil { - panic(err) - } - delete(cache.directory, key) - cache.size-- - cache.mutex.Unlock() - - keyMutex.Unlock() - - if cache.options.EvictionCallback != nil { - cache.options.EvictionCallback(key, result) - } - } - } else { - cache.mutex.RUnlock() - keyMutex.RUnlock() - } - - cache.krwMutex.Free(key) - - return -} - -func (cache *LRUCache) Contains(key interface{}) (result bool) { - keyMutex := cache.krwMutex.Register(key) - - keyMutex.RLock() - cache.mutex.RLock() - if element, exists := cache.directory[key]; exists { - cache.mutex.RUnlock() - keyMutex.RUnlock() - - cache.mutex.Lock() - cache.promoteElement(element) - cache.mutex.Unlock() - - result = true - } else { - cache.mutex.RUnlock() - keyMutex.RUnlock() - - result = false - } - - cache.krwMutex.Free(key) - - return -} - -func (cache *LRUCache) Get(key interface{}) (result interface{}) { - keyMutex := cache.krwMutex.Register(key) - - keyMutex.RLock() - cache.mutex.RLock() - if element, exists := cache.directory[key]; exists { - cache.mutex.RUnlock() - cache.mutex.Lock() - cache.promoteElement(element) - cache.mutex.Unlock() - - result = element.GetValue().(*lruCacheElement).value - - } else { - cache.mutex.RUnlock() - } - - keyMutex.RUnlock() - cache.krwMutex.Free(key) - - return -} - -func (cache *LRUCache) GetCapacity() int { - cache.mutex.RLock() - defer cache.mutex.RUnlock() - - return cache.capacity -} - -func (cache *LRUCache) GetSize() int { - cache.mutex.RLock() - defer cache.mutex.RUnlock() - - return cache.size -} - -func (cache *LRUCache) Delete(key interface{}) bool { - keyMutex := cache.krwMutex.Register(key) - keyMutex.Lock() - - cache.mutex.RLock() - - entry, exists := cache.directory[key] - if exists { - cache.mutex.RUnlock() - cache.mutex.Lock() - defer cache.mutex.Unlock() - - if err := cache.doublyLinkedList.removeEntry(entry); err != nil { - panic(err) - } - delete(cache.directory, key) - - cache.size-- - keyMutex.Unlock() - - if cache.options.EvictionCallback != nil { - cache.options.EvictionCallback(key, entry.GetValue().(*lruCacheElement).value) - } - - return true - } - - cache.mutex.RUnlock() - - keyMutex.Unlock() - cache.krwMutex.Free(key) - - return false -} - -func (cache *LRUCache) promoteElement(element *DoublyLinkedListEntry) { - if err := cache.doublyLinkedList.removeEntry(element); err != nil { - panic(err) - } - cache.doublyLinkedList.addFirstEntry(element) -} diff --git a/packages/datastructure/lru_cache_options.go b/packages/datastructure/lru_cache_options.go deleted file mode 100644 index 61f0e9c1fabd4697e16ce48e58f24ce2c07d7238..0000000000000000000000000000000000000000 --- a/packages/datastructure/lru_cache_options.go +++ /dev/null @@ -1,15 +0,0 @@ -package datastructure - -import ( - "time" -) - -type LRUCacheOptions struct { - EvictionCallback func(key interface{}, value interface{}) - IdleTimeout time.Duration -} - -var DEFAULT_OPTIONS = &LRUCacheOptions{ - EvictionCallback: nil, - IdleTimeout: 30 * time.Second, -} diff --git a/packages/datastructure/lru_cache_test.go b/packages/datastructure/lru_cache_test.go deleted file mode 100644 index 5d314374e9133c30b97e34fcb251ff945f57719d..0000000000000000000000000000000000000000 --- a/packages/datastructure/lru_cache_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package datastructure - -import ( - "testing" -) - -func TestLRUCache(t *testing.T) { - cache := NewLRUCache(5) - - cache.ComputeIfAbsent("test", func() interface{} { - return 12 - }) - - if cache.Get("test") != 12 { - t.Error("the cache does not contain the added elements") - } - - if cache.GetSize() != 1 { - t.Error("the size should be 1") - } - - if cache.GetCapacity() != 5 { - t.Error("the capacity should be 5") - } - - cache.Set("a", 3) - cache.Set("b", 4) - cache.Set("c", 5) - cache.Set("d", 6) - - if cache.GetSize() != 5 { - t.Error("the size should be 5") - } - - cache.Set("e", 7) - - if cache.GetSize() != 5 { - t.Error("the size should be 5") - } - - if cache.Get("test") != nil { - t.Error("'test' should have been dropped") - } - - cache.Set("a", 6) - cache.Set("f", 8) - - if cache.GetSize() != 5 { - t.Error("the size should be 5") - } - - if cache.Get("a") == nil { - t.Error("'a' should not have been dropped") - } - if cache.Get("b") != nil { - t.Error("'b' should have been dropped") - } - - { - key, value := "test2", 1337 - - cache.ComputeIfAbsent(key, func() interface{} { - return value - }) - if cache.Get(key) != value { - t.Error("'" + key + "' should have been added") - } - } - - if cache.GetSize() != 5 { - t.Error("the size should be 5") - } - - if cache.Get("a") != nil { - cache.Delete("a") - } - if cache.GetSize() != 4 { - t.Error("the size should be 4") - } - - cache.Delete("f") - if cache.GetSize() != 3 { - t.Error("the size should be 3") - } -} - -func TestLRUCache_ComputeIfPresent(t *testing.T) { - cache := NewLRUCache(5) - cache.Set(8, 9) - - cache.ComputeIfPresent(8, func(value interface{}) interface{} { - return 88 - }) - if cache.Get(8) != 88 || cache.GetSize() != 1 { - t.Error("cache was not updated correctly") - } - - cache.ComputeIfPresent(8, func(value interface{}) interface{} { - return nil - }) - if cache.Get(8) != nil || cache.GetSize() != 0 { - t.Error("cache was not updated correctly") - } -} diff --git a/packages/datastructure/random_map.go b/packages/datastructure/random_map.go deleted file mode 100644 index 7e43230797dae96ac5fe2eb342276acd151e210c..0000000000000000000000000000000000000000 --- a/packages/datastructure/random_map.go +++ /dev/null @@ -1,121 +0,0 @@ -package datastructure - -import ( - "math/rand" - "sync" - "time" -) - -func init() { - rand.Seed(time.Now().UnixNano()) -} - -type randomMapEntry struct { - key interface{} - value interface{} - keyIndex int -} - -type RandomMap struct { - rawMap map[interface{}]*randomMapEntry - keys []interface{} - size int - mutex sync.RWMutex -} - -func NewRandomMap() *RandomMap { - return &RandomMap{ - rawMap: make(map[interface{}]*randomMapEntry), - keys: make([]interface{}, 0), - } -} - -func (rmap *RandomMap) Set(key interface{}, value interface{}) { - rmap.mutex.Lock() - - if entry, exists := rmap.rawMap[key]; exists { - entry.value = value - } else { - rmap.rawMap[key] = &randomMapEntry{ - key: key, - value: value, - keyIndex: rmap.size, - } - - rmap.keys = append(rmap.keys, key) - - rmap.size++ - } - - rmap.mutex.Unlock() -} - -func (rmap *RandomMap) Get(key interface{}) (result interface{}, exists bool) { - rmap.mutex.RLock() - - if entry, entryExists := rmap.rawMap[key]; entryExists { - result = entry.value - exists = entryExists - } - - rmap.mutex.RUnlock() - - return -} - -func (rmap *RandomMap) Delete(key interface{}) (result interface{}, exists bool) { - rmap.mutex.RLock() - - if _, entryExists := rmap.rawMap[key]; entryExists { - rmap.mutex.RUnlock() - rmap.mutex.Lock() - - if entry, entryExists := rmap.rawMap[key]; entryExists { - delete(rmap.rawMap, key) - - rmap.size-- - - if entry.keyIndex != rmap.size { - oldKey := entry.keyIndex - movedKey := rmap.keys[rmap.size] - - rmap.rawMap[movedKey].keyIndex = oldKey - - rmap.keys[oldKey] = movedKey - } - - rmap.keys = rmap.keys[:rmap.size] - - result = entry.value - exists = true - } - - rmap.mutex.Unlock() - } else { - rmap.mutex.RUnlock() - } - - return -} - -func (rmap *RandomMap) Size() (result int) { - rmap.mutex.RLock() - - result = rmap.size - - rmap.mutex.RUnlock() - - return -} - -func (rmap *RandomMap) RandomEntry() (result interface{}) { - rmap.mutex.RLock() - - if rmap.size >= 1 { - result = rmap.rawMap[rmap.keys[rand.Intn(rmap.size)]].value - } - - rmap.mutex.RUnlock() - - return -}