From 762083eeb04025bbb53a3a2e9579038ee0d70d3c Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 11:09:36 +0300 Subject: [PATCH 01/11] HW4 is completed --- hw04_lru_cache/go.mod | 2 +- hw04_lru_cache/list.go | 133 ++++++++++++++++++++++++++++++++++-- hw04_lru_cache/list_test.go | 40 +++++++++++ 3 files changed, 170 insertions(+), 5 deletions(-) diff --git a/hw04_lru_cache/go.mod b/hw04_lru_cache/go.mod index b4abc63..fdf7771 100644 --- a/hw04_lru_cache/go.mod +++ b/hw04_lru_cache/go.mod @@ -1,4 +1,4 @@ -module github.com/fixme_my_friend/hw04_lru_cache +module github.com/ezhk/golang-learning/hw04_lru_cache go 1.14 diff --git a/hw04_lru_cache/list.go b/hw04_lru_cache/list.go index eab309f..ce35dd3 100644 --- a/hw04_lru_cache/list.go +++ b/hw04_lru_cache/list.go @@ -1,17 +1,142 @@ package hw04_lru_cache //nolint:golint,stylecheck type List interface { - // Place your code here + Len() int // длина списка + Front() *listItem // первый Item + Back() *listItem // последний Item + PushFront(v interface{}) *listItem // добавить значение в начало + PushBack(v interface{}) *listItem // добавить значение в конец + Remove(i *listItem) // удалить элемент + MoveToFront(i *listItem) // переместить элемент в начало + ShowElements() []listItem // показать все элементы списка } type listItem struct { - // Place your code here + Value interface{} // значение + Next *listItem // следующий элемент + Prev *listItem // предыдущий элемент } type list struct { - // Place your code here + // using on delete validation + elementsSet map[*listItem]struct{} + + // Length stay for back compatibility when we cannot use map + Length int + + First *listItem + Last *listItem } func NewList() List { - return &list{} + return &list{ + elementsSet: make(map[*listItem]struct{}), + Length: 0, + } +} + +func (l *list) Len() int { + // also we can use len(l.elementsSet) + return l.Length +} + +func (l *list) Front() *listItem { + return l.First +} + +func (l *list) Back() *listItem { + return l.Last +} + +func (l *list) PushFront(v interface{}) *listItem { + switch l.Len() { + case 0: + l.First = &listItem{Value: v} + l.Last = l.First + default: + value := &listItem{ + Value: v, + Next: l.First, + } + l.First.Prev = value + l.First = value + } + + l.Length++ + l.elementsSet[l.First] = struct{}{} + + return l.First +} + +func (l *list) PushBack(v interface{}) *listItem { + switch l.Len() { + case 0: + l.Last = &listItem{Value: v} + l.First = l.Last + default: + value := &listItem{ + Value: v, + Prev: l.Last, + } + l.Last.Next = value + l.Last = value + } + + l.Length++ + l.elementsSet[l.Last] = struct{}{} + + return l.Last +} + +func (l *list) Remove(i *listItem) { + if _, ok := l.elementsSet[i]; !ok { + return + } + + switch l.Len() { + case 0: + // back compatibility for disabled elementsSet + return + case 1: + l.First = nil + l.Last = nil + case 2: + if i == l.First { + l.First = l.Last + } else { + l.Last = l.First + } + l.First.Next = nil + l.Last.Prev = nil + default: + switch { + // remove first element + case i == l.First: + i.Next.Prev = nil + l.First = i.Next + // remove last element + case i == l.Last: + i.Prev.Next = nil + l.Last = i.Prev + // remove middle element + default: + i.Prev.Next, i.Next.Prev = i.Next, i.Prev + } + } + + delete(l.elementsSet, i) + l.Length-- +} + +func (l *list) MoveToFront(i *listItem) { + l.Remove(i) + l.PushFront(i.Value) +} + +func (l *list) ShowElements() []listItem { + elements := make([]listItem, 0, l.Len()) + for key := range l.elementsSet { + elements = append(elements, *key) + } + return elements } diff --git a/hw04_lru_cache/list_test.go b/hw04_lru_cache/list_test.go index 78e1f57..2b71153 100644 --- a/hw04_lru_cache/list_test.go +++ b/hw04_lru_cache/list_test.go @@ -15,6 +15,46 @@ func TestList(t *testing.T) { require.Nil(t, l.Back()) }) + t.Run("zero or one element", func(t *testing.T) { + l := NewList() + + l.PushFront(10) + require.Equal(t, l.Len(), 1) + // validate internal struct: when last and first are equals + require.Equal(t, l.Front(), l.Back()) + + elems := make([]int, 0, l.Len()) + for i := l.Front(); i != nil; i = i.Next { + elems = append(elems, i.Value.(int)) + } + require.Equal(t, elems, []int{10}) + require.Equal(t, l.ShowElements(), []listItem{*l.Front()}) + + l.Remove(l.Front()) + require.Equal(t, l.Len(), 0) + require.Equal(t, l.Front(), (*listItem)(nil)) + require.Equal(t, l.Back(), (*listItem)(nil)) + }) + + t.Run("two elements", func(t *testing.T) { + l := NewList() + l.PushFront("begin") + l.PushBack("end") + require.Equal(t, l.Len(), 2) + + elems := make([]string, 0, l.Len()) + for i := l.Front(); i != nil; i = i.Next { + elems = append(elems, i.Value.(string)) + } + require.Equal(t, elems, []string{"begin", "end"}) + + l.Remove(l.Front()) + require.Equal(t, l.Len(), 1) + + // validate last value + require.Equal(t, l.Back().Value.(string), "end") + }) + t.Run("complex", func(t *testing.T) { l := NewList() From d1a9359de6f22a107f934cb48c141f06f01d6006 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 19:41:51 +0300 Subject: [PATCH 02/11] LRU logic released --- hw04_lru_cache/cache.go | 62 ++++++++++++++++++++++++++++++++---- hw04_lru_cache/cache_test.go | 52 ++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 10 deletions(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index 738399e..83b7c8e 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -3,20 +3,68 @@ package hw04_lru_cache //nolint:golint,stylecheck type Key string type Cache interface { - // Place your code here + Set(key string, value interface{}) bool + Get(key string) (interface{}, bool) + Clear() } type lruCache struct { - // Place your code here: - // - capacity - // - queue - // - items + capacity int + Queue List + Items map[string]*listItem } type cacheItem struct { - // Place your code here + cKey string + cValue interface{} } func NewCache(capacity int) Cache { - return &lruCache{} + list := NewList() + return &lruCache{ + capacity: capacity, + Queue: list, + Items: make(map[string]*listItem), + } +} + +func (c lruCache) Set(key string, value interface{}) bool { + if item, ok := c.Items[key]; ok { + ci := item.Value.(cacheItem) + ci.cValue = value + item.Value = ci + + c.Queue.MoveToFront(item) + return true + } + + for c.Queue.Len() >= c.capacity { + latestItem := c.Queue.Back() + + c.Queue.Remove(latestItem) + delete(c.Items, latestItem.Value.(cacheItem).cKey) + } + + item := cacheItem{ + cKey: key, + cValue: value, + } + c.Items[key] = c.Queue.PushFront(item) + return false +} + +func (c lruCache) Get(key string) (interface{}, bool) { + if item, ok := c.Items[key]; ok { + c.Queue.MoveToFront(item) + return (item.Value).(cacheItem).cValue, true + } + + return nil, false +} + +func (c lruCache) Clear() { + for c.Queue.Len() > 0 { + c.Queue.Remove(c.Queue.Back()) + } + c.Items = make(map[string]*listItem) } diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go index e99447d..de4a487 100644 --- a/hw04_lru_cache/cache_test.go +++ b/hw04_lru_cache/cache_test.go @@ -50,7 +50,53 @@ func TestCache(t *testing.T) { }) t.Run("purge logic", func(t *testing.T) { - // Write me + c := NewCache(1) + + wasInCache := c.Set("aaa", 100) + require.False(t, wasInCache) + + wasInCache = c.Set("bbb", 200) + require.False(t, wasInCache) + + val, ok := c.Get("aaa") + require.False(t, ok) + require.Equal(t, nil, val) + + val, ok = c.Get("bbb") + require.True(t, ok) + require.Equal(t, 200, val) + }) + + t.Run("push logic", func(t *testing.T) { + c := NewCache(3) + + c.Set("aaa", 100) + c.Set("bbb", 200) + c.Set("ccc", 300) + + // make aaa and bbb more frequent + c.Get("aaa") + c.Get("bbb") + + c.Set("ddd", 400) + + // check purged value + val, ok := c.Get("ccc") + require.False(t, ok) + require.Equal(t, nil, val) + + // check exist values + val, ok = c.Get("aaa") + require.True(t, ok) + require.Equal(t, 100, val) + + val, ok = c.Get("bbb") + require.True(t, ok) + require.Equal(t, 200, val) + + val, ok = c.Get("ddd") + require.True(t, ok) + require.Equal(t, 400, val) }) } @@ -64,14 +110,14 @@ func TestCacheMultithreading(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 1_000_000; i++ { - c.Set(Key(strconv.Itoa(i)), i) + c.Set(strconv.Itoa(i), i) } }() go func() { defer wg.Done() for i := 0; i < 1_000_000; i++ { - c.Get(Key(strconv.Itoa(rand.Intn(1_000_000)))) + c.Get(strconv.Itoa(rand.Intn(1_000_000))) } }() From d641487b72bc41bd387f9ecfa33cbaf0307e5ce5 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 19:53:57 +0300 Subject: [PATCH 03/11] Optimize update value of exist cache element --- hw04_lru_cache/cache.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index 83b7c8e..5a37ea9 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -28,12 +28,16 @@ func NewCache(capacity int) Cache { } } +func NewItem(key string, value interface{}) *cacheItem { + return &cacheItem{ + cKey: key, + cValue: value, + } +} + func (c lruCache) Set(key string, value interface{}) bool { if item, ok := c.Items[key]; ok { - ci := item.Value.(cacheItem) - ci.cValue = value - item.Value = ci - + item.Value.(*cacheItem).cValue = value c.Queue.MoveToFront(item) return true } @@ -42,13 +46,10 @@ func (c lruCache) Set(key string, value interface{}) bool { latestItem := c.Queue.Back() c.Queue.Remove(latestItem) - delete(c.Items, latestItem.Value.(cacheItem).cKey) + delete(c.Items, latestItem.Value.(*cacheItem).cKey) } - item := cacheItem{ - cKey: key, - cValue: value, - } + item := NewItem(key, value) c.Items[key] = c.Queue.PushFront(item) return false } @@ -56,7 +57,7 @@ func (c lruCache) Set(key string, value interface{}) bool { func (c lruCache) Get(key string) (interface{}, bool) { if item, ok := c.Items[key]; ok { c.Queue.MoveToFront(item) - return (item.Value).(cacheItem).cValue, true + return (item.Value).(*cacheItem).cValue, true } return nil, false From 7f76dd131e37404d71a8820f71ff57c88c80a8a9 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 19:55:33 +0300 Subject: [PATCH 04/11] remove not used () --- hw04_lru_cache/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index 5a37ea9..6919cde 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -57,7 +57,7 @@ func (c lruCache) Set(key string, value interface{}) bool { func (c lruCache) Get(key string) (interface{}, bool) { if item, ok := c.Items[key]; ok { c.Queue.MoveToFront(item) - return (item.Value).(*cacheItem).cValue, true + return item.Value.(*cacheItem).cValue, true } return nil, false From 0e014c442675c8c65c4082a9d0ccd6a70f1afb29 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 21:02:03 +0300 Subject: [PATCH 05/11] update key type --- hw04_lru_cache/cache.go | 23 +++++++++++------------ hw04_lru_cache/cache_test.go | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index 6919cde..cf59819 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -3,39 +3,38 @@ package hw04_lru_cache //nolint:golint,stylecheck type Key string type Cache interface { - Set(key string, value interface{}) bool - Get(key string) (interface{}, bool) + Set(key Key, value interface{}) bool + Get(key Key) (interface{}, bool) Clear() } type lruCache struct { capacity int Queue List - Items map[string]*listItem + Items map[Key]*listItem } type cacheItem struct { - cKey string + cKey Key cValue interface{} } func NewCache(capacity int) Cache { - list := NewList() return &lruCache{ capacity: capacity, - Queue: list, - Items: make(map[string]*listItem), + Queue: NewList(), + Items: make(map[Key]*listItem), } } -func NewItem(key string, value interface{}) *cacheItem { +func newItem(key Key, value interface{}) *cacheItem { return &cacheItem{ cKey: key, cValue: value, } } -func (c lruCache) Set(key string, value interface{}) bool { +func (c lruCache) Set(key Key, value interface{}) bool { if item, ok := c.Items[key]; ok { item.Value.(*cacheItem).cValue = value c.Queue.MoveToFront(item) @@ -49,12 +48,12 @@ func (c lruCache) Set(key string, value interface{}) bool { delete(c.Items, latestItem.Value.(*cacheItem).cKey) } - item := NewItem(key, value) + item := newItem(key, value) c.Items[key] = c.Queue.PushFront(item) return false } -func (c lruCache) Get(key string) (interface{}, bool) { +func (c lruCache) Get(key Key) (interface{}, bool) { if item, ok := c.Items[key]; ok { c.Queue.MoveToFront(item) return item.Value.(*cacheItem).cValue, true @@ -67,5 +66,5 @@ func (c lruCache) Clear() { for c.Queue.Len() > 0 { c.Queue.Remove(c.Queue.Back()) } - c.Items = make(map[string]*listItem) + c.Items = make(map[Key]*listItem) } diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go index de4a487..0574d8c 100644 --- a/hw04_lru_cache/cache_test.go +++ b/hw04_lru_cache/cache_test.go @@ -110,14 +110,14 @@ func TestCacheMultithreading(t *testing.T) { go func() { defer wg.Done() for i := 0; i < 1_000_000; i++ { - c.Set(strconv.Itoa(i), i) + c.Set(Key(strconv.Itoa(i)), i) } }() go func() { defer wg.Done() for i := 0; i < 1_000_000; i++ { - c.Get(strconv.Itoa(rand.Intn(1_000_000))) + c.Get(Key(strconv.Itoa(rand.Intn(1_000_000)))) } }() From 1a7eb5050c6cc4906e255d6d2efd0c868bd5afb5 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 21:21:52 +0300 Subject: [PATCH 06/11] make cache goroutine safely --- hw04_lru_cache/cache.go | 18 +++++++++++++++--- hw04_lru_cache/cache_test.go | 2 -- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index cf59819..e827cfd 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -1,5 +1,7 @@ package hw04_lru_cache //nolint:golint,stylecheck +import "sync" + type Key string type Cache interface { @@ -9,6 +11,7 @@ type Cache interface { } type lruCache struct { + sync.Mutex capacity int Queue List Items map[Key]*listItem @@ -34,7 +37,10 @@ func newItem(key Key, value interface{}) *cacheItem { } } -func (c lruCache) Set(key Key, value interface{}) bool { +func (c *lruCache) Set(key Key, value interface{}) bool { + c.Lock() + defer c.Unlock() + if item, ok := c.Items[key]; ok { item.Value.(*cacheItem).cValue = value c.Queue.MoveToFront(item) @@ -53,7 +59,10 @@ func (c lruCache) Set(key Key, value interface{}) bool { return false } -func (c lruCache) Get(key Key) (interface{}, bool) { +func (c *lruCache) Get(key Key) (interface{}, bool) { + c.Lock() + defer c.Unlock() + if item, ok := c.Items[key]; ok { c.Queue.MoveToFront(item) return item.Value.(*cacheItem).cValue, true @@ -62,7 +71,10 @@ func (c lruCache) Get(key Key) (interface{}, bool) { return nil, false } -func (c lruCache) Clear() { +func (c *lruCache) Clear() { + c.Lock() + defer c.Unlock() + for c.Queue.Len() > 0 { c.Queue.Remove(c.Queue.Back()) } diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go index 0574d8c..e2a3101 100644 --- a/hw04_lru_cache/cache_test.go +++ b/hw04_lru_cache/cache_test.go @@ -101,8 +101,6 @@ func TestCache(t *testing.T) { } func TestCacheMultithreading(t *testing.T) { - t.Skip() // Remove if task with asterisk completed - c := NewCache(10) wg := &sync.WaitGroup{} wg.Add(2) From 4e08912dcd38b3949e4e2e9d435101016b5edc5c Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Sun, 21 Jun 2020 21:29:47 +0300 Subject: [PATCH 07/11] Clear() test cases added --- hw04_lru_cache/cache.go | 4 +++- hw04_lru_cache/cache_test.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index e827cfd..7823c26 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -1,6 +1,8 @@ package hw04_lru_cache //nolint:golint,stylecheck -import "sync" +import ( + "sync" +) type Key string diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go index e2a3101..d685d8e 100644 --- a/hw04_lru_cache/cache_test.go +++ b/hw04_lru_cache/cache_test.go @@ -98,6 +98,19 @@ func TestCache(t *testing.T) { require.True(t, ok) require.Equal(t, 400, val) }) + + t.Run("clear", func(t *testing.T) { + c := NewCache(1) + + c.Set("aaa", 100) + c.Set("bbb", 200) + _, ok := c.Get("aaa") + require.False(t, ok) + + c.Clear() + _, ok = c.Get("bbb") + require.False(t, ok) + }) } func TestCacheMultithreading(t *testing.T) { @@ -119,5 +132,12 @@ func TestCacheMultithreading(t *testing.T) { } }() + go func() { + defer wg.Done() + for i := 0; i < 1_000_000; i++ { + c.Clear() + } + }() + wg.Wait() } From fa9f4ca51b1019b939dc78ebe3db95e46982e0b0 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Mon, 22 Jun 2020 10:17:32 +0300 Subject: [PATCH 08/11] update gorouting count --- hw04_lru_cache/cache_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw04_lru_cache/cache_test.go b/hw04_lru_cache/cache_test.go index d685d8e..6a20158 100644 --- a/hw04_lru_cache/cache_test.go +++ b/hw04_lru_cache/cache_test.go @@ -116,7 +116,7 @@ func TestCache(t *testing.T) { func TestCacheMultithreading(t *testing.T) { c := NewCache(10) wg := &sync.WaitGroup{} - wg.Add(2) + wg.Add(3) go func() { defer wg.Done() From 480174f1b274a8114ec76d2c2d0541e341230af3 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Thu, 25 Jun 2020 17:48:54 +0300 Subject: [PATCH 09/11] codereview patches --- hw04_lru_cache/list.go | 69 +++++++++---------------------------- hw04_lru_cache/list_test.go | 1 - 2 files changed, 16 insertions(+), 54 deletions(-) diff --git a/hw04_lru_cache/list.go b/hw04_lru_cache/list.go index ce35dd3..3d96b3c 100644 --- a/hw04_lru_cache/list.go +++ b/hw04_lru_cache/list.go @@ -8,7 +8,6 @@ type List interface { PushBack(v interface{}) *listItem // добавить значение в конец Remove(i *listItem) // удалить элемент MoveToFront(i *listItem) // переместить элемент в начало - ShowElements() []listItem // показать все элементы списка } type listItem struct { @@ -18,9 +17,6 @@ type listItem struct { } type list struct { - // using on delete validation - elementsSet map[*listItem]struct{} - // Length stay for back compatibility when we cannot use map Length int @@ -29,14 +25,10 @@ type list struct { } func NewList() List { - return &list{ - elementsSet: make(map[*listItem]struct{}), - Length: 0, - } + return &list{} } func (l *list) Len() int { - // also we can use len(l.elementsSet) return l.Length } @@ -63,8 +55,6 @@ func (l *list) PushFront(v interface{}) *listItem { } l.Length++ - l.elementsSet[l.First] = struct{}{} - return l.First } @@ -83,48 +73,29 @@ func (l *list) PushBack(v interface{}) *listItem { } l.Length++ - l.elementsSet[l.Last] = struct{}{} - return l.Last } func (l *list) Remove(i *listItem) { - if _, ok := l.elementsSet[i]; !ok { - return - } - - switch l.Len() { - case 0: - // back compatibility for disabled elementsSet - return - case 1: + switch { + // element in the middle + case i.Prev != nil && i.Next != nil: + i.Prev.Next = i.Next + i.Next.Prev = i.Prev + // element in the left/begin + case i.Prev != nil: + l.Last = i.Prev + i.Prev.Next = nil + // element in the right/end + case i.Next != nil: + l.First = i.Next + i.Next.Prev = nil + // stay only one element + default: l.First = nil l.Last = nil - case 2: - if i == l.First { - l.First = l.Last - } else { - l.Last = l.First - } - l.First.Next = nil - l.Last.Prev = nil - default: - switch { - // remove first element - case i == l.First: - i.Next.Prev = nil - l.First = i.Next - // remove last element - case i == l.Last: - i.Prev.Next = nil - l.Last = i.Prev - // remove middle element - default: - i.Prev.Next, i.Next.Prev = i.Next, i.Prev - } } - delete(l.elementsSet, i) l.Length-- } @@ -132,11 +103,3 @@ func (l *list) MoveToFront(i *listItem) { l.Remove(i) l.PushFront(i.Value) } - -func (l *list) ShowElements() []listItem { - elements := make([]listItem, 0, l.Len()) - for key := range l.elementsSet { - elements = append(elements, *key) - } - return elements -} diff --git a/hw04_lru_cache/list_test.go b/hw04_lru_cache/list_test.go index 2b71153..bc30563 100644 --- a/hw04_lru_cache/list_test.go +++ b/hw04_lru_cache/list_test.go @@ -28,7 +28,6 @@ func TestList(t *testing.T) { elems = append(elems, i.Value.(int)) } require.Equal(t, elems, []int{10}) - require.Equal(t, l.ShowElements(), []listItem{*l.Front()}) l.Remove(l.Front()) require.Equal(t, l.Len(), 0) From a73ffc064d63baa061e9341409dffef51b940c6b Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Thu, 25 Jun 2020 17:53:33 +0300 Subject: [PATCH 10/11] clean by creating new empty list --- hw04_lru_cache/cache.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw04_lru_cache/cache.go b/hw04_lru_cache/cache.go index 7823c26..7ea7aaf 100644 --- a/hw04_lru_cache/cache.go +++ b/hw04_lru_cache/cache.go @@ -77,8 +77,6 @@ func (c *lruCache) Clear() { c.Lock() defer c.Unlock() - for c.Queue.Len() > 0 { - c.Queue.Remove(c.Queue.Back()) - } + c.Queue = NewList() c.Items = make(map[Key]*listItem) } From 742ed02e256375088ce6f9912ae3110a10069b06 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Thu, 25 Jun 2020 21:47:51 +0300 Subject: [PATCH 11/11] update comments --- hw04_lru_cache/list.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw04_lru_cache/list.go b/hw04_lru_cache/list.go index 3d96b3c..7e899e9 100644 --- a/hw04_lru_cache/list.go +++ b/hw04_lru_cache/list.go @@ -82,11 +82,11 @@ func (l *list) Remove(i *listItem) { case i.Prev != nil && i.Next != nil: i.Prev.Next = i.Next i.Next.Prev = i.Prev - // element in the left/begin + // element in the right/end case i.Prev != nil: l.Last = i.Prev i.Prev.Next = nil - // element in the right/end + // element in the left/begin case i.Next != nil: l.First = i.Next i.Next.Prev = nil